1 //! The `Pid` type.
2 
3 #![allow(unsafe_code)]
4 
5 use crate::backend::c;
6 use core::num::NonZeroI32;
7 
8 /// A process identifier as a raw integer.
9 pub type RawPid = c::pid_t;
10 
11 /// `pid_t`—A non-zero Unix process ID.
12 ///
13 /// This is a pid, and not a pidfd. It is not a file descriptor, and the
14 /// process it refers to could disappear at any time and be replaced by
15 /// another, unrelated, process.
16 #[repr(transparent)]
17 #[derive(Copy, Clone, Eq, PartialEq, Debug, Hash)]
18 pub struct Pid(NonZeroI32);
19 
20 impl Pid {
21     /// A `Pid` corresponding to the init process (pid 1).
22     pub const INIT: Self = Self(match NonZeroI32::new(1) {
23         Some(n) => n,
24         None => panic!("unreachable"),
25     });
26 
27     /// Converts a `RawPid` into a `Pid`.
28     ///
29     /// Returns `Some` for positive `RawPid`s. Otherwise, returns `None`.
30     ///
31     /// This is safe because a `Pid` is a number without any guarantees for the
32     /// kernel. Non-child `Pid`s are always racy for any syscalls, but can only
33     /// cause logic errors. If you want race-free access to or control of
34     /// non-child processes, please consider other mechanisms like [pidfd] on
35     /// Linux.
36     ///
37     /// [pidfd]: https://man7.org/linux/man-pages/man2/pidfd_open.2.html
38     #[inline]
from_raw(raw: RawPid) -> Option<Self>39     pub const fn from_raw(raw: RawPid) -> Option<Self> {
40         if raw > 0 {
41             // SAFETY: We just checked that `raw > 0`.
42             unsafe { Some(Self::from_raw_unchecked(raw)) }
43         } else {
44             None
45         }
46     }
47 
48     /// Converts a known positive `RawPid` into a `Pid`.
49     ///
50     /// # Safety
51     ///
52     /// The caller must guarantee `raw` is positive.
53     #[inline]
from_raw_unchecked(raw: RawPid) -> Self54     pub const unsafe fn from_raw_unchecked(raw: RawPid) -> Self {
55         debug_assert!(raw > 0);
56         Self(NonZeroI32::new_unchecked(raw))
57     }
58 
59     /// Creates a `Pid` holding the ID of the given child process.
60     #[cfg(feature = "std")]
61     #[inline]
from_child(child: &std::process::Child) -> Self62     pub fn from_child(child: &std::process::Child) -> Self {
63         let id = child.id();
64         // SAFETY: We know the returned ID is valid because it came directly
65         // from an OS API.
66         unsafe { Self::from_raw_unchecked(id as i32) }
67     }
68 
69     /// Converts a `Pid` into a `NonZeroI32`.
70     #[inline]
as_raw_nonzero(self) -> NonZeroI3271     pub const fn as_raw_nonzero(self) -> NonZeroI32 {
72         self.0
73     }
74 
75     /// Converts an `Option<Pid>` into a `RawPid`.
76     #[inline]
as_raw(pid: Option<Self>) -> RawPid77     pub fn as_raw(pid: Option<Self>) -> RawPid {
78         pid.map_or(0, |pid| pid.0.get())
79     }
80 
81     /// Test whether this pid represents the init process (pid 1).
82     #[inline]
is_init(self) -> bool83     pub const fn is_init(self) -> bool {
84         self.0.get() == Self::INIT.0.get()
85     }
86 }
87 
88 #[test]
test_sizes()89 fn test_sizes() {
90     use core::mem::transmute;
91 
92     assert_eq_size!(RawPid, NonZeroI32);
93     assert_eq_size!(RawPid, Pid);
94     assert_eq_size!(RawPid, Option<Pid>);
95 
96     // Rustix doesn't depend on `Option<Pid>` matching the ABI of a raw integer
97     // for correctness, but it should work nonetheless.
98     const_assert_eq!(0 as RawPid, unsafe {
99         transmute::<Option<Pid>, RawPid>(None)
100     });
101     const_assert_eq!(4567 as RawPid, unsafe {
102         transmute::<Option<Pid>, RawPid>(Some(Pid::from_raw_unchecked(4567)))
103     });
104 }
105