@@ -62,13 +62,14 @@ fn test_command_fork_no_unwind() {
62
62
}
63
63
64
64
#[ test]
65
- #[ cfg( target_os = "linux" ) ]
65
+ #[ cfg( target_os = "linux" ) ] // pidfds are a linux-specific concept
66
66
fn test_command_pidfd ( ) {
67
67
use crate :: assert_matches:: assert_matches;
68
68
use crate :: os:: fd:: { AsRawFd , RawFd } ;
69
69
use crate :: os:: linux:: process:: { ChildExt , CommandExt } ;
70
70
use crate :: process:: Command ;
71
71
72
+ // pidfds require the pidfd_open syscall
72
73
let our_pid = crate :: process:: id ( ) ;
73
74
let pidfd = unsafe { libc:: syscall ( libc:: SYS_pidfd_open , our_pid, 0 ) } ;
74
75
let pidfd_open_available = if pidfd >= 0 {
@@ -81,7 +82,9 @@ fn test_command_pidfd() {
81
82
// always exercise creation attempts
82
83
let mut child = Command :: new ( "false" ) . create_pidfd ( true ) . spawn ( ) . unwrap ( ) ;
83
84
84
- // but only check if we know that the kernel supports pidfds
85
+ // but only check if we know that the kernel supports pidfds.
86
+ // We don't assert the precise value, since the standard library
87
+ // might have opened other file descriptors before our code runs.
85
88
if pidfd_open_available {
86
89
assert ! ( child. pidfd( ) . is_ok( ) ) ;
87
90
}
@@ -97,4 +100,17 @@ fn test_command_pidfd() {
97
100
child. kill ( ) . expect ( "failed to kill child" ) ;
98
101
let status = child. wait ( ) . expect ( "error waiting on pidfd" ) ;
99
102
assert_eq ! ( status. signal( ) , Some ( libc:: SIGKILL ) ) ;
103
+
104
+ let _ = Command :: new ( "echo" )
105
+ . create_pidfd ( false )
106
+ . spawn ( )
107
+ . unwrap ( )
108
+ . pidfd ( )
109
+ . expect_err ( "pidfd should not have been created when create_pid(false) is set" ) ;
110
+
111
+ let _ = Command :: new ( "echo" )
112
+ . spawn ( )
113
+ . unwrap ( )
114
+ . pidfd ( )
115
+ . expect_err ( "pidfd should not have been created" ) ;
100
116
}
0 commit comments