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
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
//! 特定于 Linux 的 [`std::process`] 模块中的原语扩展。
//!
//! [`std::process`]: crate::process

#![unstable(feature = "linux_pidfd", issue = "82971")]

use crate::io::Result;
use crate::os::unix::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, OwnedFd, RawFd};
use crate::process;
use crate::sealed::Sealed;
#[cfg(not(doc))]
use crate::sys::fd::FileDesc;
use crate::sys_common::{AsInner, AsInnerMut, FromInner, IntoInner};

#[cfg(doc)]
struct FileDesc;

/// 此类型表示引用进程的文件描述符。
///
/// `PidFd` 可以通过设置 [`Command`] 和 [`create_pidfd`] 上的相应选项来获得。随后,可以通过调用 [`pidfd`] 或 [`take_pidfd`] 从 [`Child`] 中检索创建的 pidfd。
///
/// Example:
///
/// ```no_run
/// #![feature(linux_pidfd)]
/// use std::os::linux::process::{CommandExt, ChildExt};
/// use std::process::Command;
///
/// let mut child = Command::new("echo")
///     .create_pidfd(true)
///     .spawn()
///     .expect("Failed to spawn child");
///
/// let pidfd = child
///     .take_pidfd()
///     .expect("Failed to retrieve pidfd");
///
/// // 当 `pidfd` 关闭时,文件描述符将被关闭。
/// ```
///
/// 有关详细信息,请参见 [`pidfd_open(2)`] 的手册页。
///
/// [`Command`]: process::Command
/// [`create_pidfd`]: CommandExt::create_pidfd
/// [`Child`]: process::Child
/// [`pidfd`]: fn@ChildExt::pidfd
/// [`take_pidfd`]: ChildExt::take_pidfd
/// [`pidfd_open(2)`]: https://man7.org/linux/man-pages/man2/pidfd_open.2.html
#[derive(Debug)]
pub struct PidFd {
    inner: FileDesc,
}

impl AsInner<FileDesc> for PidFd {
    #[inline]
    fn as_inner(&self) -> &FileDesc {
        &self.inner
    }
}

impl FromInner<FileDesc> for PidFd {
    fn from_inner(inner: FileDesc) -> PidFd {
        PidFd { inner }
    }
}

impl IntoInner<FileDesc> for PidFd {
    fn into_inner(self) -> FileDesc {
        self.inner
    }
}

impl AsRawFd for PidFd {
    #[inline]
    fn as_raw_fd(&self) -> RawFd {
        self.as_inner().as_raw_fd()
    }
}

impl FromRawFd for PidFd {
    unsafe fn from_raw_fd(fd: RawFd) -> Self {
        Self::from_inner(FileDesc::from_raw_fd(fd))
    }
}

impl IntoRawFd for PidFd {
    fn into_raw_fd(self) -> RawFd {
        self.into_inner().into_raw_fd()
    }
}

impl AsFd for PidFd {
    fn as_fd(&self) -> BorrowedFd<'_> {
        self.as_inner().as_fd()
    }
}

impl From<OwnedFd> for PidFd {
    fn from(fd: OwnedFd) -> Self {
        Self::from_inner(FileDesc::from_inner(fd))
    }
}

impl From<PidFd> for OwnedFd {
    fn from(pid_fd: PidFd) -> Self {
        pid_fd.into_inner().into_inner()
    }
}

/// 特定于操作系统的 [`Child`] 的扩展
///
/// [`Child`]: process::Child
pub trait ChildExt: Sealed {
    /// 获取对为此 [`Child`] 创建的 [`PidFd`] 的引用 (如果可用)。
    ///
    /// 只有在创建相应的 [`Command`] 时使用 [`create_pidfd`] 请求创建 pidfd 时,pidfd 才可用。
    ///
    ///
    /// 即使请求,pidfd 也可能不可用,因为正在使用旧版本的 Linux,或者如果发生了一些其他错误。
    ///
    /// [`Command`]: process::Command
    /// [`create_pidfd`]: CommandExt::create_pidfd
    /// [`Child`]: process::Child
    ///
    fn pidfd(&self) -> Result<&PidFd>;

    /// 拥有为此 [`Child`] 创建的 [`PidFd`] (如果可用) 的所有权。
    ///
    /// 只有在创建相应的 [`Command`] 时使用 [`create_pidfd`] 请求创建 pidfd 时,pidfd 才可用。
    ///
    ///
    /// 即使请求,pidfd 也可能不可用,因为正在使用旧版本的 Linux,或者如果发生了一些其他错误。
    ///
    /// [`Command`]: process::Command
    /// [`create_pidfd`]: CommandExt::create_pidfd
    /// [`Child`]: process::Child
    ///
    fn take_pidfd(&mut self) -> Result<PidFd>;
}

/// 特定于操作系统的 [`Command`] 的扩展
///
/// [`Command`]: process::Command
pub trait CommandExt: Sealed {
    /// 设置是否应为此 [`Command`] 生成的 [`Child`] 创建 [`PidFd`](struct@PidFd)。
    ///
    /// 默认情况下,不会创建 pidfd。
    ///
    /// 可以使用 [`pidfd`] 或 [`take_pidfd`] 从子节点那里检索 pidfd。
    ///
    /// pidfd 只会在有可能以保证无竞争的方式 (例如
    /// 如果支持 `clone3` 系统调用)。
    /// 否则,[`pidfd`] 将返回错误。
    ///
    /// [`Command`]: process::Command
    /// [`Child`]: process::Child
    /// [`pidfd`]: fn@ChildExt::pidfd
    /// [`take_pidfd`]: ChildExt::take_pidfd
    fn create_pidfd(&mut self, val: bool) -> &mut process::Command;
}

impl CommandExt for process::Command {
    fn create_pidfd(&mut self, val: bool) -> &mut process::Command {
        self.as_inner_mut().create_pidfd(val);
        self
    }
}