interprocess Rust library
repository·main·Indexed 20 days ago
https://github.com/kotauskas/interprocessA Rust inter-process communication (IPC) toolkit providing a uniform interface across Windows and Unix-like systems. It offers high-performance alternatives to TCP localhost sockets via local sockets, unnamed pipes, FIFO files (Unix), and named pipes (Windows). The library supports asynchronous I/O via the Tokio runtime and provides platform-specific extensions through the os module.
What's inside interprocess
- To minimize the risk of LLM contamination from third-party dependencies that form part of the public API, certain dependencies are gated behind off-by-default features. This allows users to opt-in to specific functionality while maintaining a cleaner dependency profile by default.
Understand platform support and compatibility
mainInterprocess supports Windows and generic Unix-like systems. Platform-specific extensions are exposed via
#[cfg]gates. If you attempt to use a feature on a platform that does not support it, you will encounter a compile error rather than a runtime error.Support Levels
- Explicit support (Windows, Linux, macOS): Guaranteed to compile and pass all tests in CI.
- Explicit support with incomplete CI (FreeBSD, Android): Expected to compile and pass tests; CI runs Clippy and Rustdoc via cross-compilation.
- Explicit support without CI (OpenBSD, NetBSD): Expected to compile and pass tests; verified via manual testing.
- Support by association (Dragonfly BSD, Redox, Fuchsia, iOS, tvOS, watchOS): Expected to compile and pass tests based on identical behavior to higher-tier platforms.
- Assumed support (Other
#[cfg(unix)]systems): Expected to work, but bugs are considered low priority.
Choose an Interprocess communication primitive
mainInterprocess provides several IPC (Inter-Process Communication) interfaces depending on your requirements.
- Local sockets: The flagship feature. Use these instead of
localhostTCP sockets for better performance and easier authentication/identification. If you are unsure where to start, begin with thelocal_socketmodule. - Unnamed pipes: Use these when the standard pipes provided by
std::processare insufficient. - FIFO files (Unix only): Primarily useful for communicating with programs that specifically require FIFO files (often used in shell scripting).
- Named pipes (Windows only): The Windows counterpart to Unix domain sockets, used to implement local sockets.
- Local sockets: The flagship feature. Use these instead of
Use Asynchronous I/O with Tokio
mainInterprocess supports asynchronous I/O via the Tokio runtime.
- Local sockets and Windows named pipes are provided directly by Interprocess for async use.
- Unix domain sockets are available via Tokio's own implementation.
Note: Support for the
smolruntime is not currently being actively worked on.Verify LLM-free status for compliance
mainIf your project or organization has restrictions prohibiting the use of LLM-generated dependencies,
interprocesscan be safely added to your allowlist. The author guarantees that LLMs have not been used in the development of this software and that LLM-generated code is not present in the source tree.Note on Transitive Dependencies: While an effort is made to avoid dependencies containing LLM-generated code, the author cannot guarantee a total lack of such software in the entire transitive dependency tree. If you discover LLM usage in upstream dependencies, you are encouraged to report it on the project's issue tracker.
Understand PipeStream flushing and limbo behavior
mainThe
PipeStreamimplementation includes specialized handling for data integrity during connection termination and flushing efficiency.Connection Termination (Thunking)
To prevent unexpected errors during shutdown,
ERROR_PIPE_NOT_CONNECTEDandstd::io::ErrorKind::BrokenPipeare translated into:Ok(0)(EOF) for bytestreams.RecvResult::EndOfStreamfor message streams.
The Limbo Thread Pool
To ensure the peer receives all sent data before the handle is closed,
PipeStreamuses a thread pool called limbo.- When a stream is dropped, if it contains unsent data (hasn't been flushed since the last send), the handle is sent to the limbo pool.
- The limbo pool ensures handles are flushed before being closed, preventing the peer from receiving a
BrokenPipeor EOF prematurely. - Limbo Elision: If a stream has not performed any sends since its last explicit flush, it will bypass the limbo pool to avoid unnecessary overhead. You can force limbo behavior using
.mark_dirty().
Flushing Optimization
- Consecutive
.flush()calls on a stream that hasn't sent new data since the last flush are elided (treated as a no-op) to improve performance.
How local socket name types affect implementation dispatch
mainIn
interprocess, the way you define a local socket name determines which underlying OS implementation (e.g., Unix Domain Sockets vs. Windows Named Pipes) is used. This is achieved through type-level markers that implement thePathNameTypeorNamespacedNameTypetraits.To use these, you do not implement the traits yourself (they are sealed). Instead, you pass these tag types as generic arguments to the following conversion methods:
- For filesystem paths: Use
ToFsName::to_fs_name()with a type implementingPathNameType. - For namespaced strings: Use
ToNsName::to_ns_name()with a type implementingNamespacedNameType.
Choosing the correct name type ensures your code correctly maps inputs to the intended local socket implementation for the target platform.
- For filesystem paths: Use
Use GenericNamespaced for platform-agnostic namespaced strings
mainThe
GenericNamespacedtag type provides a consistent mapping from arbitrary OS strings to local socket names across different platforms.Platform Behavior
- Windows: Resolves to named pipe names by prepending
\.\pipe\(addressing local named pipes only). - Linux: Resolves to the abstract namespace with no transformations (maximum length of 107 bytes).
- Other Unices: Resolves to filesystem paths by prepending
/tmp/.
To use this, pass
GenericNamespacedtoToNsName::to_ns_name().- Windows: Resolves to named pipe names by prepending
Use platform-specific IPC primitives via the os module
mainThe
interprocesscrate provides platform-specific implementations for various interprocess communication (IPC) primitives through theosmodule. Depending on your target platform, you will use eitherinterprocess::os::unixorinterprocess::os::windows.- Unix-like systems (Linux, macOS, FreeBSD): Access primitives via
interprocess::os::unix. - Windows: Access primitives via
interprocess::os::windows.
If you are viewing documentation on Docs.rs, you can switch between these platform views using the 'Platform' menu in the header bar to see the specific APIs available for each OS.
- Unix-like systems (Linux, macOS, FreeBSD): Access primitives via
Handle Windows-specific named pipe connection behavior
mainWhen using local sockets on Windows (which are implemented via named pipes), it is critical to call
.accept()(or iterate via.incoming()) periodically.If a client connects and then immediately disconnects before the server calls
accept, the named pipe instance enters a 'dead-on-arrival' state. This state will prevent new clients from connecting until the existing connection is cleared by a call toaccept.Communicate pipe handles to child processes
mainSince unnamed pipes are only accessible via their handles, you can pass the numeric handle/file descriptor to a child process to establish communication.
- In the parent process: Use
AsRawHandle(Windows) orAsRawFd(Unix) to get the numeric value of theSenderorRecver. - Transfer: Pass this value to the child process via a command-line argument or an environment variable.
- In the child process: Reconstruct the I/O object using
FromRawHandleorFromRawFdfrom the standard library.
Note:
interprocessdoes not manage the transfer mechanism itself; it only provides the handles.- In the parent process: Use
Configure the `tokio` feature gate
mainTo use the asynchronous variants of IPC primitives provided by Interprocess, you must enable the
tokiofeature in yourCargo.toml.By default, this feature is off.
[dependencies] interprocess = { version = "2.4.3", features = ["tokio"] }