@@ -11,25 +11,44 @@ fn test_pidfd_open() {
1111
1212#[ cfg( feature = "signal" ) ]
1313mod send_signal {
14+ use std:: {
15+ io:: { IoSlice , IoSliceMut } ,
16+ os:: fd:: { AsFd as _, AsRawFd as _, FromRawFd as _, OwnedFd , RawFd } ,
17+ } ;
18+
1419 use nix:: {
1520 sys:: {
1621 pidfd:: {
1722 pidfd_open, pidfd_send_signal, PidfdOpenFlags ,
1823 PidfdSendSignalFlags ,
1924 } ,
2025 signal:: Signal ,
21- wait:: { waitpid, WaitStatus } ,
26+ socket:: {
27+ recvmsg, sendmsg, socketpair, AddressFamily , ControlMessage ,
28+ ControlMessageOwned , MsgFlags , SockFlag , SockType ,
29+ } ,
30+ wait:: { waitid, Id , WaitPidFlag , WaitStatus } ,
2231 } ,
2332 unistd:: { fork, getpid, ForkResult } ,
2433 } ;
2534
2635 #[ test]
2736 fn test_pidfd_send_signal ( ) {
2837 // NOTE: This function MUST be async-signal-safe.
29- fn child_process ( ) -> ! {
38+ fn child_process ( socket : OwnedFd ) -> ! {
3039 let pidfd = pidfd_open ( getpid ( ) , PidfdOpenFlags :: empty ( ) )
3140 . unwrap_or_else ( |_| std:: process:: exit ( 1 ) ) ;
3241
42+ // Send PIDFD to the parent.
43+ sendmsg :: < ( ) > (
44+ socket. as_raw_fd ( ) ,
45+ & [ IoSlice :: new ( & [ ] ) ] ,
46+ & [ ControlMessage :: ScmRights ( & [ pidfd. as_raw_fd ( ) ] ) ] ,
47+ MsgFlags :: empty ( ) ,
48+ None ,
49+ )
50+ . unwrap_or_else ( |_| std:: process:: exit ( 1 ) ) ;
51+
3352 // Code beyond this call should be unreachable.
3453 pidfd_send_signal (
3554 & pidfd,
@@ -42,21 +61,53 @@ mod send_signal {
4261 std:: process:: exit ( 1 )
4362 }
4463
64+ let ( socket, child_socket) = socketpair (
65+ AddressFamily :: Unix ,
66+ SockType :: SeqPacket ,
67+ None ,
68+ SockFlag :: empty ( ) ,
69+ )
70+ . expect ( "should be able to create socketpair" ) ;
71+
4572 // SAFETY: `child_process` is async-signal-safe.
46- let child = unsafe {
73+ unsafe {
4774 match fork ( ) . expect ( "should be able to fork" ) {
48- ForkResult :: Parent { child } => child ,
49- ForkResult :: Child => child_process ( ) ,
75+ ForkResult :: Child => child_process ( child_socket ) ,
76+ ForkResult :: Parent { .. } => ( ) ,
5077 }
5178 } ;
5279
80+ let mut iov = [ IoSliceMut :: new ( & mut [ ] ) ] ;
81+ let mut cmsg = cmsg_space ! ( RawFd ) ;
82+
83+ let msg = recvmsg :: < ( ) > (
84+ socket. as_raw_fd ( ) ,
85+ & mut iov,
86+ Some ( & mut cmsg) ,
87+ MsgFlags :: empty ( ) ,
88+ )
89+ . expect ( "should be able to call recvmsg" ) ;
90+
91+ let cmsg = msg
92+ . cmsgs ( )
93+ . expect ( "should be able to receive cmsgs" )
94+ . next ( )
95+ . expect ( "should receive 1 cmsg" ) ;
96+
97+ let child_pidfd = if let ControlMessageOwned :: ScmRights ( fds) = cmsg {
98+ if let [ fd] = & * fds {
99+ // SAFETY: SCM_RIGHTS provides valid file descriptors.
100+ unsafe { OwnedFd :: from_raw_fd ( RawFd :: from ( * fd) ) }
101+ } else {
102+ panic ! ( "should receive one file descriptor" ) ;
103+ }
104+ } else {
105+ panic ! ( "should receive an SCM_RIGHTS cmsg" ) ;
106+ } ;
107+
53108 assert ! ( matches!(
54- waitpid( child, None ) ,
55- Ok ( WaitStatus :: Signaled (
56- x,
57- Signal :: SIGKILL ,
58- _
59- ) ) if x == child
109+ waitid( Id :: PIDFd ( child_pidfd. as_fd( ) ) , WaitPidFlag :: WEXITED ) ,
110+ Ok ( WaitStatus :: Signaled ( _, Signal :: SIGKILL , _) )
60111 ) ) ;
61112 }
62113}
0 commit comments