66
77use  crate :: io:: Result ; 
88use  crate :: os:: unix:: io:: { AsFd ,  AsRawFd ,  BorrowedFd ,  FromRawFd ,  IntoRawFd ,  OwnedFd ,  RawFd } ; 
9- use  crate :: process; 
9+ use  crate :: process:: { self ,   ExitStatus } ; 
1010use  crate :: sealed:: Sealed ; 
1111#[ cfg( not( doc) ) ]  
12- use  crate :: sys:: fd:: FileDesc ; 
12+ use  crate :: sys:: { fd:: FileDesc ,  linux :: pidfd :: PidFd   as   InnerPidFd } ; 
1313use  crate :: sys_common:: { AsInner ,  AsInnerMut ,  FromInner ,  IntoInner } ; 
1414
1515#[ cfg( doc) ]  
16- struct  FileDesc ; 
16+ struct  InnerPidFd ; 
1717
1818/// This type represents a file descriptor that refers to a process. 
1919/// 
2020/// A `PidFd` can be obtained by setting the corresponding option on [`Command`] 
2121/// 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 `]. 
2323/// 
2424/// Example: 
2525/// ```no_run 
@@ -33,7 +33,7 @@ struct FileDesc;
3333///     .expect("Failed to spawn child"); 
3434/// 
3535/// let pidfd = child 
36- ///     .take_pidfd () 
36+ ///     .into_pidfd () 
3737///     .expect("Failed to retrieve pidfd"); 
3838/// 
3939/// // The file descriptor will be closed when `pidfd` is dropped. 
@@ -44,66 +44,101 @@ struct FileDesc;
4444/// [`create_pidfd`]: CommandExt::create_pidfd 
4545/// [`Child`]: process::Child 
4646/// [`pidfd`]: fn@ChildExt::pidfd 
47- /// [`take_pidfd `]: ChildExt::take_pidfd  
47+ /// [`into_pidfd `]: ChildExt::into_pidfd  
4848/// [`pidfd_open(2)`]: https://man7.org/linux/man-pages/man2/pidfd_open.2.html 
4949#[ derive( Debug ) ]  
50+ #[ repr( transparent) ]  
5051pub  struct  PidFd  { 
51-     inner :  FileDesc , 
52+     inner :  InnerPidFd , 
5253} 
5354
54- impl  AsInner < FileDesc >  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 < ExitStatus >  { 
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 < ExitStatus > >  { 
85+         Ok ( self . inner . try_wait ( ) ?. map ( FromInner :: from_inner) ) 
86+     } 
87+ } 
88+ 
89+ impl  AsInner < InnerPidFd >  for  PidFd  { 
5590    #[ inline]  
56-     fn  as_inner ( & self )  -> & FileDesc  { 
91+     fn  as_inner ( & self )  -> & InnerPidFd  { 
5792        & self . inner 
5893    } 
5994} 
6095
61- impl  FromInner < FileDesc >  for  PidFd  { 
62-     fn  from_inner ( inner :  FileDesc )  -> PidFd  { 
96+ impl  FromInner < InnerPidFd >  for  PidFd  { 
97+     fn  from_inner ( inner :  InnerPidFd )  -> PidFd  { 
6398        PidFd  {  inner } 
6499    } 
65100} 
66101
67- impl  IntoInner < FileDesc >  for  PidFd  { 
68-     fn  into_inner ( self )  -> FileDesc  { 
102+ impl  IntoInner < InnerPidFd >  for  PidFd  { 
103+     fn  into_inner ( self )  -> InnerPidFd  { 
69104        self . inner 
70105    } 
71106} 
72107
73108impl  AsRawFd  for  PidFd  { 
74109    #[ inline]  
75110    fn  as_raw_fd ( & self )  -> RawFd  { 
76-         self . as_inner ( ) . as_raw_fd ( ) 
111+         self . as_inner ( ) . as_inner ( ) . as_raw_fd ( ) 
77112    } 
78113} 
79114
80115impl  FromRawFd  for  PidFd  { 
81116    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) ) 
83118    } 
84119} 
85120
86121impl  IntoRawFd  for  PidFd  { 
87122    fn  into_raw_fd ( self )  -> RawFd  { 
88-         self . into_inner ( ) . into_raw_fd ( ) 
123+         self . into_inner ( ) . into_inner ( ) . into_raw_fd ( ) 
89124    } 
90125} 
91126
92127impl  AsFd  for  PidFd  { 
93128    fn  as_fd ( & self )  -> BorrowedFd < ' _ >  { 
94-         self . as_inner ( ) . as_fd ( ) 
129+         self . as_inner ( ) . as_inner ( ) . as_fd ( ) 
95130    } 
96131} 
97132
98133impl  From < OwnedFd >  for  PidFd  { 
99134    fn  from ( fd :  OwnedFd )  -> Self  { 
100-         Self :: from_inner ( FileDesc :: from_inner ( fd) ) 
135+         Self :: from_inner ( InnerPidFd :: from_inner ( FileDesc :: from_inner ( fd) ) ) 
101136    } 
102137} 
103138
104139impl  From < PidFd >  for  OwnedFd  { 
105140    fn  from ( pid_fd :  PidFd )  -> Self  { 
106-         pid_fd. into_inner ( ) . into_inner ( ) 
141+         pid_fd. into_inner ( ) . into_inner ( ) . into_inner ( ) 
107142    } 
108143} 
109144
@@ -124,18 +159,26 @@ pub trait ChildExt: Sealed {
124159/// [`Child`]: process::Child 
125160fn  pidfd ( & self )  -> Result < & PidFd > ; 
126161
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. 
128164/// 
129165/// A pidfd will only be available if its creation was requested with 
130166/// [`create_pidfd`] when the corresponding [`Command`] was created. 
131167/// 
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+ /// 
132172/// Even if requested, a pidfd may not be available due to an older 
133173/// version of Linux being in use, or if some other error occurred. 
134174/// 
135175/// [`Command`]: process::Command 
136176/// [`create_pidfd`]: CommandExt::create_pidfd 
177+ /// [`pidfd`]: ChildExt::pidfd 
137178/// [`Child`]: process::Child 
138- fn  take_pidfd ( & mut  self )  -> Result < PidFd > ; 
179+ fn  into_pidfd ( self )  -> crate :: result:: Result < PidFd ,  Self > 
180+     where 
181+         Self :  Sized ; 
139182} 
140183
141184/// Os-specific extensions for [`Command`] 
@@ -146,7 +189,7 @@ pub trait CommandExt: Sealed {
146189/// spawned by this [`Command`]. 
147190/// By default, no pidfd will be created. 
148191/// 
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 `]. 
150193/// 
151194/// A pidfd will only be created if it is possible to do so 
152195/// in a guaranteed race-free manner. Otherwise, [`pidfd`] will return an error. 
@@ -160,7 +203,7 @@ pub trait CommandExt: Sealed {
160203/// [`Command`]: process::Command 
161204/// [`Child`]: process::Child 
162205/// [`pidfd`]: fn@ChildExt::pidfd 
163- /// [`take_pidfd `]: ChildExt::take_pidfd  
206+ /// [`into_pidfd `]: ChildExt::into_pidfd  
164207fn  create_pidfd ( & mut  self ,  val :  bool )  -> & mut  process:: Command ; 
165208} 
166209
0 commit comments