@@ -18,8 +18,8 @@ use crate::ffi::CStr;
1818#[ cfg( feature = "fs" ) ]
1919use crate :: fs:: AtFlags ;
2020use crate :: io;
21- use crate :: pid:: Pid ;
22- use crate :: runtime:: { How , Sigaction , Siginfo , Sigset , Stack } ;
21+ use crate :: pid:: { Pid , RawPid } ;
22+ use crate :: runtime:: { Fork , How , Sigaction , Siginfo , Sigset , Stack } ;
2323use crate :: signal:: Signal ;
2424use crate :: timespec:: Timespec ;
2525use crate :: utils:: option_as_ptr;
@@ -33,16 +33,48 @@ use linux_raw_sys::prctl::PR_SET_NAME;
3333use { crate :: backend:: conv:: ret_infallible, linux_raw_sys:: general:: ARCH_SET_FS } ;
3434
3535#[ inline]
36- pub ( crate ) unsafe fn fork ( ) -> io:: Result < Option < Pid > > {
36+ pub ( crate ) unsafe fn fork ( ) -> io:: Result < Fork > {
37+ let mut child_pid = MaybeUninit :: < RawPid > :: uninit ( ) ;
38+
39+ // Unix `fork` only returns the child PID in the parent; we'd like it in
40+ // the child too, so set `CLONE_CHILD_SETTID` and pass in the address of
41+ // a memory location to store it to in the child.
42+ //
43+ // Architectures differ on the order of the parameters.
44+ #[ cfg( target_arch = "x86_64" ) ]
3745 let pid = ret_c_int ( syscall_readonly ! (
3846 __NR_clone,
39- c_int( c:: SIGCHLD ) ,
40- zero( ) ,
47+ c_int( c:: SIGCHLD | c:: CLONE_CHILD_SETTID ) ,
4148 zero( ) ,
4249 zero( ) ,
50+ & mut child_pid,
4351 zero( )
4452 ) ) ?;
45- Ok ( Pid :: from_raw ( pid) )
53+ #[ cfg( any(
54+ target_arch = "aarch64" ,
55+ target_arch = "arm" ,
56+ target_arch = "mips" ,
57+ target_arch = "mips32r6" ,
58+ target_arch = "mips64" ,
59+ target_arch = "mips64r6" ,
60+ target_arch = "powerpc64" ,
61+ target_arch = "riscv64" ,
62+ target_arch = "x86"
63+ ) ) ]
64+ let pid = ret_c_int ( syscall_readonly ! (
65+ __NR_clone,
66+ c_int( c:: SIGCHLD | c:: CLONE_CHILD_SETTID ) ,
67+ zero( ) ,
68+ zero( ) ,
69+ zero( ) ,
70+ & mut child_pid
71+ ) ) ?;
72+
73+ Ok ( if let Some ( pid) = Pid :: from_raw ( pid) {
74+ Fork :: Parent ( pid)
75+ } else {
76+ Fork :: Child ( Pid :: from_raw_unchecked ( child_pid. assume_init ( ) ) )
77+ } )
4678}
4779
4880#[ cfg( feature = "fs" ) ]
0 commit comments