pidfd-util-rs
Safe Rust wrapper for Linux process file descriptors (pidfd).
This crate provides a safe, ergonomic interface to Linux's pidfd API, which represents processes as file descriptors. Unlike traditional PIDs, pidfds cannot be reused after a process exits, making them safe from PID reuse race conditions.
Features
- Safe process operations: Send signals, wait for exit, query process information
- PID reuse protection: Pidfds remain valid and unique even after process termination
- Modern kernel support: Uses modern kernel APIs when available, falls back to older methods
- Async support: Optional async operations via the
asyncfeature (enabled by default) - Nightly compatibility: Uses stdlib's
PidFdon nightly, provides own implementation on stable
Installation
Add this to your Cargo.toml:
[]
= { = "0.1.0", = "https://github.com/swick/pidfd-util-rs.git" }
Obtaining a PidFd
The typical ways to obtain a pidfd include:
- Using
clone3withCLONE_PIDFD: On nightly Rust, usestd::process::Commandwithcreate_pidfd(true)and then callinto_pidfd()on the child process. - Clearing the
CLOEXECflag and exec'ing: Clear the close-on-exec flag usinglibc::fcntlwithlibc::F_SETFD, then exec the target process. - Passing via UNIX socket: Use
sendmsg/recvmsgon a UNIX socket to pass the file descriptor between processes. This is exposed instd::os::unix::net::UnixStream::recv_vectored_with_ancillary.
⚠️ Warning: While PidFd::from_pid() exists, its use is highly discouraged. There is a race condition where the process with the PID dies and a new process gets assigned the same recycled PID, causing the resulting pidfd to refer to the wrong process.
Usage
Basic Example (Nightly)
use ;
use ;
use Command;
Async Example
use ;
async
Core Types
PidFd: The main type representing a process file descriptorPidFdExt: Extension trait providing additional operations (get PID, credentials, namespaces, etc.)AsyncPidFd: Async wrapper for waiting on process exit (requiresasyncfeature)PidfdCreds: Process credential information (UID, GID variants)PidfdGetNamespace: Namespace types that can be queried
Key Operations
Process Information
get_pid()- Get the process ID of the process referred to by the pidfdget_ppid()- Get the parent process IDget_id()- Get a unique, non-reusable process identifier (useful for logging)get_creds()- Get process credentials (UIDs/GIDs)get_cgroupid()- Get the cgroup ID
Process Control
kill()- Send SIGKILL to the processsend_signal()- Send any signal to the processwait()- Wait for process exit (blocking)try_wait()- Check if process has exited (non-blocking)
Advanced Operations
get_namespace()- Get a file descriptor to a process namespaceset_namespace()- Move the calling process into a namespace of the target processget_remote_fd()- Duplicate a file descriptor from another processaccess_proc()- Execute a function with PID reuse protection
Kernel Requirements
- Basic pidfd support requires Linux 5.3+
- Some operations require newer kernels (automatically detected with fallback where possible)
Cargo Features
async(default): EnablesAsyncPidFdfor async process waitingnightly: Uses stdlib'sPidFdimplementation on nightly Rust
License
This project is licensed under either of:
- MIT License
- Apache License, Version 2.0
at your option.