11//! Tests for the `pidfd` type.
22
3- use libc:: { kill, SIGSTOP } ;
3+ use libc:: { kill, SIGCONT , SIGINT , SIGSTOP } ;
44#[ cfg( feature = "event" ) ]
55use rustix:: event;
66use rustix:: fd:: AsFd as _;
@@ -24,7 +24,7 @@ fn test_pidfd_waitid() {
2424 Ok ( pidfd) => pidfd,
2525 Err ( io:: Errno :: NOSYS ) => {
2626 // The kernel does not support pidfds.
27- unsafe { kill ( child. id ( ) as _ , SIGSTOP ) } ;
27+ unsafe { kill ( child. id ( ) as _ , SIGINT ) } ;
2828 return ;
2929 }
3030 Err ( e) => panic ! ( "failed to open pidfd: {}" , e) ,
@@ -40,8 +40,154 @@ fn test_pidfd_waitid() {
4040 . expect ( "failed to wait" )
4141 . unwrap ( ) ;
4242
43- // TODO
44- let _ = status;
43+ assert ! ( status. stopped( ) ) ;
44+ assert ! ( !status. exited( ) ) ;
45+ assert ! ( !status. killed( ) ) ;
46+ assert ! ( !status. trapped( ) ) ;
47+ assert ! ( !status. dumped( ) ) ;
48+ assert ! ( !status. continued( ) ) ;
49+
50+ assert_eq ! (
51+ status. stopping_signal( ) ,
52+ Some ( process:: Signal :: STOP . as_raw( ) )
53+ ) ;
54+ assert_eq ! ( status. trapping_signal( ) , None ) ;
55+ assert_eq ! ( status. exit_status( ) , None ) ;
56+ assert_eq ! ( status. terminating_signal( ) , None ) ;
57+
58+ unsafe { kill ( child. id ( ) as _ , SIGCONT ) } ;
59+
60+ let status = process:: waitid (
61+ process:: WaitId :: PidFd ( pidfd. as_fd ( ) ) ,
62+ process:: WaitIdOptions :: CONTINUED ,
63+ )
64+ . expect ( "failed to wait" )
65+ . unwrap ( ) ;
66+
67+ assert ! ( !status. stopped( ) ) ;
68+ assert ! ( !status. exited( ) ) ;
69+ assert ! ( !status. killed( ) ) ;
70+ assert ! ( !status. trapped( ) ) ;
71+ assert ! ( !status. dumped( ) ) ;
72+ assert ! ( status. continued( ) ) ;
73+
74+ assert_eq ! ( status. stopping_signal( ) , None ) ;
75+ assert_eq ! ( status. trapping_signal( ) , None ) ;
76+ assert_eq ! ( status. exit_status( ) , None ) ;
77+ assert_eq ! ( status. terminating_signal( ) , None ) ;
78+
79+ unsafe { kill ( child. id ( ) as _ , SIGINT ) } ;
80+
81+ let status = process:: waitid (
82+ process:: WaitId :: PidFd ( pidfd. as_fd ( ) ) ,
83+ process:: WaitIdOptions :: EXITED ,
84+ )
85+ . expect ( "failed to wait" )
86+ . unwrap ( ) ;
87+
88+ assert ! ( !status. stopped( ) ) ;
89+ assert ! ( !status. exited( ) ) ;
90+ assert ! ( status. killed( ) ) ;
91+ assert ! ( !status. trapped( ) ) ;
92+ assert ! ( !status. dumped( ) ) ;
93+ assert ! ( !status. continued( ) ) ;
94+
95+ assert_eq ! ( status. stopping_signal( ) , None ) ;
96+ assert_eq ! ( status. trapping_signal( ) , None ) ;
97+ assert_eq ! ( status. exit_status( ) , None ) ;
98+ assert_eq ! ( status. terminating_signal( ) , Some ( SIGINT ) ) ;
99+ }
100+
101+ // Similar to `test_pidfd_waitid`, but use `pidfd_send_signal` to send the
102+ // signals.
103+ #[ test]
104+ #[ serial]
105+ fn test_pidfd_send_signal ( ) {
106+ // Create a new process.
107+ let child = Command :: new ( "yes" )
108+ . stdout ( std:: process:: Stdio :: null ( ) )
109+ . stderr ( std:: process:: Stdio :: null ( ) )
110+ . spawn ( )
111+ . expect ( "failed to execute child" ) ;
112+
113+ // Create a pidfd for the child process.
114+ let pid = process:: Pid :: from_child ( & child) ;
115+ let pidfd = match process:: pidfd_open ( pid, process:: PidfdFlags :: empty ( ) ) {
116+ Ok ( pidfd) => pidfd,
117+ Err ( io:: Errno :: NOSYS ) => {
118+ // The kernel does not support pidfds.
119+ process:: kill_process ( process:: Pid :: from_child ( & child) , process:: Signal :: INT ) . unwrap ( ) ;
120+ return ;
121+ }
122+ Err ( e) => panic ! ( "failed to open pidfd: {}" , e) ,
123+ } ;
124+
125+ // Wait for the child process to stop.
126+ process:: pidfd_send_signal ( & pidfd, process:: Signal :: STOP ) . unwrap ( ) ;
127+
128+ let status = process:: waitid (
129+ process:: WaitId :: PidFd ( pidfd. as_fd ( ) ) ,
130+ process:: WaitIdOptions :: STOPPED ,
131+ )
132+ . expect ( "failed to wait" )
133+ . unwrap ( ) ;
134+
135+ assert ! ( status. stopped( ) ) ;
136+ assert ! ( !status. exited( ) ) ;
137+ assert ! ( !status. killed( ) ) ;
138+ assert ! ( !status. trapped( ) ) ;
139+ assert ! ( !status. dumped( ) ) ;
140+ assert ! ( !status. continued( ) ) ;
141+
142+ assert_eq ! (
143+ status. stopping_signal( ) ,
144+ Some ( process:: Signal :: STOP . as_raw( ) )
145+ ) ;
146+ assert_eq ! ( status. trapping_signal( ) , None ) ;
147+ assert_eq ! ( status. exit_status( ) , None ) ;
148+ assert_eq ! ( status. terminating_signal( ) , None ) ;
149+
150+ process:: pidfd_send_signal ( & pidfd, process:: Signal :: CONT ) . unwrap ( ) ;
151+
152+ let status = process:: waitid (
153+ process:: WaitId :: PidFd ( pidfd. as_fd ( ) ) ,
154+ process:: WaitIdOptions :: CONTINUED ,
155+ )
156+ . expect ( "failed to wait" )
157+ . unwrap ( ) ;
158+
159+ assert ! ( !status. stopped( ) ) ;
160+ assert ! ( !status. exited( ) ) ;
161+ assert ! ( !status. killed( ) ) ;
162+ assert ! ( !status. trapped( ) ) ;
163+ assert ! ( !status. dumped( ) ) ;
164+ assert ! ( status. continued( ) ) ;
165+
166+ assert_eq ! ( status. stopping_signal( ) , None ) ;
167+ assert_eq ! ( status. trapping_signal( ) , None ) ;
168+ assert_eq ! ( status. exit_status( ) , None ) ;
169+ assert_eq ! ( status. terminating_signal( ) , None ) ;
170+
171+ process:: pidfd_send_signal ( & pidfd, process:: Signal :: INT ) . unwrap ( ) ;
172+
173+ let status = process:: waitid (
174+ process:: WaitId :: PidFd ( pidfd. as_fd ( ) ) ,
175+ process:: WaitIdOptions :: EXITED ,
176+ )
177+ . expect ( "failed to wait" )
178+ . unwrap ( ) ;
179+
180+ assert ! ( !status. stopped( ) ) ;
181+ assert ! ( !status. exited( ) ) ;
182+ assert ! ( status. killed( ) ) ;
183+ assert ! ( !status. trapped( ) ) ;
184+ assert ! ( !status. dumped( ) ) ;
185+ assert ! ( !status. continued( ) ) ;
186+
187+ assert_eq ! ( status. stopping_signal( ) , None ) ;
188+ assert_eq ! ( status. trapping_signal( ) , None ) ;
189+ assert_eq ! ( status. exit_status( ) , None ) ;
190+ assert_eq ! ( status. terminating_signal( ) , Some ( SIGINT ) ) ;
45191}
46192
47193#[ cfg( feature = "event" ) ]
@@ -62,6 +208,7 @@ fn test_pidfd_poll() {
62208 Ok ( pidfd) => pidfd,
63209 Err ( io:: Errno :: NOSYS ) | Err ( io:: Errno :: INVAL ) => {
64210 // The kernel does not support non-blocking pidfds.
211+ process:: kill_process ( process:: Pid :: from_child ( & child) , process:: Signal :: INT ) . unwrap ( ) ;
65212 return ;
66213 }
67214 Err ( e) => panic ! ( "failed to open pidfd: {}" , e) ,
@@ -89,6 +236,15 @@ fn test_pidfd_poll() {
89236 . expect ( "failed to wait" )
90237 . unwrap ( ) ;
91238
92- // TODO
93- let _ = status;
239+ assert ! ( !status. stopped( ) ) ;
240+ assert ! ( status. exited( ) ) ;
241+ assert ! ( !status. killed( ) ) ;
242+ assert ! ( !status. trapped( ) ) ;
243+ assert ! ( !status. dumped( ) ) ;
244+ assert ! ( !status. continued( ) ) ;
245+
246+ assert_eq ! ( status. stopping_signal( ) , None ) ;
247+ assert_eq ! ( status. trapping_signal( ) , None ) ;
248+ assert_eq ! ( status. exit_status( ) , Some ( 0 ) ) ;
249+ assert_eq ! ( status. terminating_signal( ) , None ) ;
94250}
0 commit comments