1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
// SPDX-FileCopyrightText: 2026 The pidfd-util-rs authors
// SPDX-License-Identifier: MIT OR Apache-2.0
//! 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.
//!
//! The typical ways to obtain a pidfd include:
//!
//! - **Using `clone3` with `CLONE_PIDFD`**: On nightly Rust, use `std::process::Command`
//! with `create_pidfd(true)` and then call `into_pidfd()` on the child process.
//! - **Clearing the `CLOEXEC` flag and exec'ing**: Clear the close-on-exec flag using `libc::fcntl`
//! with `libc::F_SETFD`, then exec the target process.
//! - **Passing via UNIX socket**: Use `sendmsg`/`recvmsg` on a UNIX socket to pass the file descriptor
//! between processes. This is exposed in `std::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.
//!
//! # 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 `async` feature (enabled by default)
//! - **Nightly compatibility**: Uses stdlib's `PidFd` on nightly, provides own implementation on stable
//!
//! # Core Types
//!
//! - [`PidFd`]: The main type representing a process file descriptor
//! - [`PidFdExt`]: Extension trait providing additional operations (get PID, credentials, namespaces, etc.)
//! - [`AsyncPidFd`]: Async wrapper for waiting on process exit (requires `async` feature)
//! - [`PidFdCreds`]: Process credential information (UID, GID variants)
//! - [`PidFdGetNamespace`]: Namespace types that can be queried
//!
//! # Examples
//!
//! ```no_run
//! # #![cfg_attr(feature = "nightly", feature(linux_pidfd))]
//! #
//! # use pidfd_util::{PidFd, PidFdExt};
//! # #[cfg(feature = "nightly")]
//! # use std::os::linux::process::{CommandExt, ChildExt};
//! # use std::process::Command;
//! #
//! # #[cfg(feature = "nightly")]
//! # fn spawn_child() -> PidFd {
//! # // Spawn a child process with pidfd support
//! # let mut child = Command::new("echo")
//! # .create_pidfd(true)
//! # .spawn()
//! # .expect("Failed to spawn child");
//! #
//! # // Get the pidfd for the child
//! # child
//! # .into_pidfd()
//! # .expect("Failed to retrieve pidfd")
//! # }
//! #
//! # #[cfg(not(feature = "nightly"))]
//! # fn spawn_child() -> PidFd {
//! # // Spawn a child process with pidfd support
//! # let mut child = Command::new("echo")
//! # .spawn()
//! # .expect("Failed to spawn child");
//! #
//! # // WARNING! This is racy! Don't actually do this!
//! # PidFd::from_pid(child.id().try_into().unwrap())
//! # .expect("Failed to retrieve pidfd")
//! # }
//! #
//! # fn main() -> std::io::Result<()> {
//! let pidfd = spawn_child();
//! // Query process information
//! let pid = pidfd.get_pid().expect("Failed to get the child PID");
//! let creds = pidfd.get_creds().expect("Failed to get child credentials");
//! println!("Process {} running as UID {}", pid, creds.euid);
//!
//! // Send a signal
//! pidfd.send_signal(libc::SIGTERM).expect("Failed to send SIGTERM to child");
//!
//! // Wait for process to exit
//! let status = pidfd.wait().expect("Failed to wait for child to exit");
//! println!("Process exited with status: {:?}", status);
//! # Ok(())
//! # }
//! ```
//!
//! # Kernel Requirements
//!
//! - Basic pidfd support requires Linux 5.3+
//! - Some operations require newer kernels (automatically detected with fallback where possible)
pub use *;
pub use PidFd;
pub use ;
pub use PidFdExt;
pub use AsyncPidFd;