Auto merge of #124101 - the8472:pidfd-methods, r=cuviper · model-checking/verify-rust-std@934e728 (original) (raw)

`@@ -6,20 +6,20 @@

`

6

6

``

7

7

`use crate::io::Result;

`

8

8

`use crate::os::unix::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, OwnedFd, RawFd};

`

9

``

`-

use crate::process;

`

``

9

`+

use crate::process::{self, ExitStatus};

`

10

10

`use crate::sealed::Sealed;

`

11

11

`#[cfg(not(doc))]

`

12

``

`-

use crate::sys::fd::FileDesc;

`

``

12

`+

use crate::sys::{fd::FileDesc, linux::pidfd::PidFd as InnerPidFd};

`

13

13

`use crate::sys_common::{AsInner, AsInnerMut, FromInner, IntoInner};

`

14

14

``

15

15

`#[cfg(doc)]

`

16

``

`-

struct FileDesc;

`

``

16

`+

struct InnerPidFd;

`

17

17

``

18

18

`/// This type represents a file descriptor that refers to a process.

`

19

19

`///

`

20

20

`` /// A PidFd can be obtained by setting the corresponding option on [Command]

``

21

21

`` /// with [create_pidfd]. Subsequently, the created pidfd can be retrieved

``

22

``

`` -

/// from the [Child] by calling [pidfd] or [take_pidfd].

``

``

22

`` +

/// from the [Child] by calling [pidfd] or [into_pidfd].

``

23

23

`///

`

24

24

`/// Example:

`

25

25

```` /// ```no_run

````

`@@ -33,7 +33,7 @@ struct FileDesc;

`

33

33

`/// .expect("Failed to spawn child");

`

34

34

`///

`

35

35

`/// let pidfd = child

`

36

``

`-

/// .take_pidfd()

`

``

36

`+

/// .into_pidfd()

`

37

37

`/// .expect("Failed to retrieve pidfd");

`

38

38

`///

`

39

39

`` /// // The file descriptor will be closed when pidfd is dropped.

``

`@@ -44,66 +44,101 @@ struct FileDesc;

`

44

44

`` /// [create_pidfd]: CommandExt::create_pidfd

``

45

45

`` /// [Child]: process::Child

``

46

46

`` /// [pidfd]: fn@ChildExt::pidfd

``

47

``

`` -

/// [take_pidfd]: ChildExt::take_pidfd

``

``

47

`` +

/// [into_pidfd]: ChildExt::into_pidfd

``

48

48

`` /// [pidfd_open(2)]: https://man7.org/linux/man-pages/man2/pidfd_open.2.html

``

49

49

`#[derive(Debug)]

`

``

50

`+

#[repr(transparent)]

`

50

51

`pub struct PidFd {

`

51

``

`-

inner: FileDesc,

`

``

52

`+

inner: InnerPidFd,

`

52

53

`}

`

53

54

``

54

``

`-

impl AsInner for PidFd {

`

``

55

`+

impl PidFd {

`

``

56

`+

/// Forces the child process to exit.

`

``

57

`+

///

`

``

58

`` +

/// Unlike [Child::kill] it is possible to attempt to kill

``

``

59

`+

/// reaped children since PidFd does not suffer from pid recycling

`

``

60

`+

/// races. But doing so will return an Error.

`

``

61

`+

///

`

``

62

`` +

/// [Child::kill]: process::Child::kill

``

``

63

`+

pub fn kill(&self) -> Result<()> {

`

``

64

`+

self.inner.kill()

`

``

65

`+

}

`

``

66

+

``

67

`+

/// Waits for the child to exit completely, returning the status that it exited with.

`

``

68

`+

///

`

``

69

`` +

/// Unlike [Child::wait] it does not ensure that the stdin handle is closed.

``

``

70

`` +

/// Additionally it will not return an ExitStatus if the child

``

``

71

`+

/// has already been reaped. Instead an error will be returned.

`

``

72

`+

///

`

``

73

`` +

/// [Child::wait]: process::Child::wait

``

``

74

`+

pub fn wait(&self) -> Result {

`

``

75

`+

self.inner.wait().map(FromInner::from_inner)

`

``

76

`+

}

`

``

77

+

``

78

`+

/// Attempts to collect the exit status of the child if it has already exited.

`

``

79

`+

///

`

``

80

`` +

/// Unlike [Child::try_wait] this method will return an Error

``

``

81

`+

/// if the child has already been reaped.

`

``

82

`+

///

`

``

83

`` +

/// [Child::try_wait]: process::Child::try_wait

``

``

84

`+

pub fn try_wait(&self) -> Result<Option> {

`

``

85

`+

Ok(self.inner.try_wait()?.map(FromInner::from_inner))

`

``

86

`+

}

`

``

87

`+

}

`

``

88

+

``

89

`+

impl AsInner for PidFd {

`

55

90

`#[inline]

`

56

``

`-

fn as_inner(&self) -> &FileDesc {

`

``

91

`+

fn as_inner(&self) -> &InnerPidFd {

`

57

92

`&self.inner

`

58

93

`}

`

59

94

`}

`

60

95

``

61

``

`-

impl FromInner for PidFd {

`

62

``

`-

fn from_inner(inner: FileDesc) -> PidFd {

`

``

96

`+

impl FromInner for PidFd {

`

``

97

`+

fn from_inner(inner: InnerPidFd) -> PidFd {

`

63

98

`PidFd { inner }

`

64

99

`}

`

65

100

`}

`

66

101

``

67

``

`-

impl IntoInner for PidFd {

`

68

``

`-

fn into_inner(self) -> FileDesc {

`

``

102

`+

impl IntoInner for PidFd {

`

``

103

`+

fn into_inner(self) -> InnerPidFd {

`

69

104

`self.inner

`

70

105

`}

`

71

106

`}

`

72

107

``

73

108

`impl AsRawFd for PidFd {

`

74

109

`#[inline]

`

75

110

`fn as_raw_fd(&self) -> RawFd {

`

76

``

`-

self.as_inner().as_raw_fd()

`

``

111

`+

self.as_inner().as_inner().as_raw_fd()

`

77

112

`}

`

78

113

`}

`

79

114

``

80

115

`impl FromRawFd for PidFd {

`

81

116

`unsafe fn from_raw_fd(fd: RawFd) -> Self {

`

82

``

`-

Self::from_inner(FileDesc::from_raw_fd(fd))

`

``

117

`+

Self::from_inner(InnerPidFd::from_raw_fd(fd))

`

83

118

`}

`

84

119

`}

`

85

120

``

86

121

`impl IntoRawFd for PidFd {

`

87

122

`fn into_raw_fd(self) -> RawFd {

`

88

``

`-

self.into_inner().into_raw_fd()

`

``

123

`+

self.into_inner().into_inner().into_raw_fd()

`

89

124

`}

`

90

125

`}

`

91

126

``

92

127

`impl AsFd for PidFd {

`

93

128

`fn as_fd(&self) -> BorrowedFd<'_> {

`

94

``

`-

self.as_inner().as_fd()

`

``

129

`+

self.as_inner().as_inner().as_fd()

`

95

130

`}

`

96

131

`}

`

97

132

``

98

133

`impl From for PidFd {

`

99

134

`fn from(fd: OwnedFd) -> Self {

`

100

``

`-

Self::from_inner(FileDesc::from_inner(fd))

`

``

135

`+

Self::from_inner(InnerPidFd::from_inner(FileDesc::from_inner(fd)))

`

101

136

`}

`

102

137

`}

`

103

138

``

104

139

`impl From for OwnedFd {

`

105

140

`fn from(pid_fd: PidFd) -> Self {

`

106

``

`-

pid_fd.into_inner().into_inner()

`

``

141

`+

pid_fd.into_inner().into_inner().into_inner()

`

107

142

`}

`

108

143

`}

`

109

144

``

`@@ -124,18 +159,26 @@ pub trait ChildExt: Sealed {

`

124

159

`` /// [Child]: process::Child

``

125

160

`fn pidfd(&self) -> Result<&PidFd>;

`

126

161

``

127

``

`` -

/// Takes ownership of the [PidFd] created for this [Child], if available.

``

``

162

`` +

/// Returns the [PidFd] created for this [Child], if available.

``

``

163

`+

/// Otherwise self is returned.

`

128

164

`///

`

129

165

`/// A pidfd will only be available if its creation was requested with

`

130

166

`` /// [create_pidfd] when the corresponding [Command] was created.

``

131

167

`///

`

``

168

`+

/// Taking ownership of the PidFd consumes the Child to avoid pid reuse

`

``

169

`` +

/// races. Use [pidfd] and [BorrowedFd::try_clone_to_owned] if

``

``

170

`+

/// you don't want to disassemble the Child yet.

`

``

171

`+

///

`

132

172

`/// Even if requested, a pidfd may not be available due to an older

`

133

173

`/// version of Linux being in use, or if some other error occurred.

`

134

174

`///

`

135

175

`` /// [Command]: process::Command

``

136

176

`` /// [create_pidfd]: CommandExt::create_pidfd

``

``

177

`` +

/// [pidfd]: ChildExt::pidfd

``

137

178

`` /// [Child]: process::Child

``

138

``

`-

fn take_pidfd(&mut self) -> Result;

`

``

179

`+

fn into_pidfd(self) -> crate::result::Result<PidFd, Self>

`

``

180

`+

where

`

``

181

`+

Self: Sized;

`

139

182

`}

`

140

183

``

141

184

`` /// Os-specific extensions for [Command]

``

`@@ -146,7 +189,7 @@ pub trait CommandExt: Sealed {

`

146

189

`` /// spawned by this [Command].

``

147

190

`/// By default, no pidfd will be created.

`

148

191

`///

`

149

``

`` -

/// The pidfd can be retrieved from the child with [pidfd] or [take_pidfd].

``

``

192

`` +

/// The pidfd can be retrieved from the child with [pidfd] or [into_pidfd].

``

150

193

`///

`

151

194

`/// A pidfd will only be created if it is possible to do so

`

152

195

`` /// in a guaranteed race-free manner. Otherwise, [pidfd] will return an error.

``

`@@ -160,7 +203,7 @@ pub trait CommandExt: Sealed {

`

160

203

`` /// [Command]: process::Command

``

161

204

`` /// [Child]: process::Child

``

162

205

`` /// [pidfd]: fn@ChildExt::pidfd

``

163

``

`` -

/// [take_pidfd]: ChildExt::take_pidfd

``

``

206

`` +

/// [into_pidfd]: ChildExt::into_pidfd

``

164

207

`fn create_pidfd(&mut self, val: bool) -> &mut process::Command;

`

165

208

`}

`

166

209

``