22 super :: * ,
33 nix:: {
44 errno:: Errno ,
5+ fcntl:: { FcntlArg , FdFlag } ,
56 sys:: signal:: { SaFlags , SigAction , SigHandler , SigSet } ,
67 } ,
78 std:: {
89 fs:: File ,
910 io:: Read ,
10- os:: fd:: { BorrowedFd , IntoRawFd } ,
11+ os:: fd:: { BorrowedFd , IntoRawFd , OwnedFd } ,
1112 sync:: atomic:: { self , AtomicI32 } ,
1213 } ,
1314} ;
@@ -62,6 +63,22 @@ extern "C" fn handler(signal: libc::c_int) {
6263 errno. set ( ) ;
6364}
6465
66+ fn fcntl ( fd : & OwnedFd , arg : FcntlArg ) -> RunResult < ' static , libc:: c_int > {
67+ nix:: fcntl:: fcntl ( fd, arg) . map_err ( |errno| Error :: SignalHandlerPipeCloexec {
68+ io_error : errno. into ( ) ,
69+ } )
70+ }
71+
72+ fn set_cloexec ( fd : & OwnedFd ) -> RunResult < ' static > {
73+ // It would be better to use pipe2(O_CLOEXEC) rather than pipe-then-fcntl,
74+ // but it isn't supported on all platforms (most notably, not macos) and in
75+ // the atomicity guarantees that pipe2 provides aren't needed.
76+ let existing_flags = fcntl ( fd, FcntlArg :: F_GETFD ) ?;
77+ let combined_flags = FdFlag :: from_bits_retain ( existing_flags) | FdFlag :: FD_CLOEXEC ;
78+ fcntl ( fd, FcntlArg :: F_SETFD ( combined_flags) ) ?;
79+ Ok ( ( ) )
80+ }
81+
6582pub ( crate ) struct Signals ( File ) ;
6683
6784impl Signals {
@@ -70,6 +87,9 @@ impl Signals {
7087 io_error : errno. into ( ) ,
7188 } ) ?;
7289
90+ set_cloexec ( & read) ?;
91+ set_cloexec ( & write) ?;
92+
7393 if WRITE
7494 . compare_exchange (
7595 INVALID_FILENO ,
0 commit comments