@@ -18,8 +18,8 @@ use crate::ffi::CStr;
18
18
#[ cfg( feature = "fs" ) ]
19
19
use crate :: fs:: AtFlags ;
20
20
use 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 } ;
23
23
use crate :: signal:: Signal ;
24
24
use crate :: timespec:: Timespec ;
25
25
use crate :: utils:: option_as_ptr;
@@ -33,16 +33,48 @@ use linux_raw_sys::prctl::PR_SET_NAME;
33
33
use { crate :: backend:: conv:: ret_infallible, linux_raw_sys:: general:: ARCH_SET_FS } ;
34
34
35
35
#[ 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" ) ]
37
45
let pid = ret_c_int ( syscall_readonly ! (
38
46
__NR_clone,
39
- c_int( c:: SIGCHLD ) ,
40
- zero( ) ,
47
+ c_int( c:: SIGCHLD | c:: CLONE_CHILD_SETTID ) ,
41
48
zero( ) ,
42
49
zero( ) ,
50
+ & mut child_pid,
43
51
zero( )
44
52
) ) ?;
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
+ } )
46
78
}
47
79
48
80
#[ cfg( feature = "fs" ) ]
0 commit comments