1 // Copyright 2009 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
5 // +build darwin dragonfly freebsd linux netbsd openbsd
7 // Fork, exec, wait, etc.
17 //sysnb raw_fork() (pid Pid_t, err Errno)
20 //sysnb raw_setsid() (err Errno)
23 //sysnb raw_setpgid(pid int, pgid int) (err Errno)
24 //setpgid(pid Pid_t, pgid Pid_t) _C_int
26 //sysnb raw_chroot(path *byte) (err Errno)
27 //chroot(path *byte) _C_int
29 //sysnb raw_chdir(path *byte) (err Errno)
30 //chdir(path *byte) _C_int
32 //sysnb raw_fcntl(fd int, cmd int, arg int) (val int, err Errno)
33 //__go_fcntl(fd _C_int, cmd _C_int, arg _C_int) _C_int
35 //sysnb raw_close(fd int) (err Errno)
36 //close(fd _C_int) _C_int
38 //sysnb raw_ioctl(fd int, cmd int, val int) (rval int, err Errno)
39 //ioctl(fd _C_int, cmd _C_int, val _C_int) _C_int
41 //sysnb raw_execve(argv0 *byte, argv **byte, envv **byte) (err Errno)
42 //execve(argv0 *byte, argv **byte, envv **byte) _C_int
44 //sysnb raw_write(fd int, buf *byte, count int) (err Errno)
45 //write(fd _C_int, buf *byte, count Size_t) Ssize_t
47 //sysnb raw_exit(status int)
48 //_exit(status _C_int)
50 //sysnb raw_dup2(oldfd int, newfd int) (err Errno)
51 //dup2(oldfd _C_int, newfd _C_int) _C_int
53 // Lock synchronizing creation of new file descriptors with fork.
55 // We want the child in a fork/exec sequence to inherit only the
56 // file descriptors we intend. To do that, we mark all file
57 // descriptors close-on-exec and then, in the child, explicitly
58 // unmark the ones we want the exec'ed program to keep.
59 // Unix doesn't make this easy: there is, in general, no way to
60 // allocate a new file descriptor close-on-exec. Instead you
61 // have to allocate the descriptor and then mark it close-on-exec.
62 // If a fork happens between those two events, the child's exec
63 // will inherit an unwanted file descriptor.
65 // This lock solves that race: the create new fd/mark close-on-exec
66 // operation is done holding ForkLock for reading, and the fork itself
67 // is done holding ForkLock for writing. At least, that's the idea.
68 // There are some complications.
70 // Some system calls that create new file descriptors can block
71 // for arbitrarily long times: open on a hung NFS server or named
72 // pipe, accept on a socket, and so on. We can't reasonably grab
73 // the lock across those operations.
75 // It is worse to inherit some file descriptors than others.
76 // If a non-malicious child accidentally inherits an open ordinary file,
77 // that's not a big deal. On the other hand, if a long-lived child
78 // accidentally inherits the write end of a pipe, then the reader
79 // of that pipe will not see EOF until that child exits, potentially
80 // causing the parent program to hang. This is a common problem
81 // in threaded C programs that use popen.
83 // Luckily, the file descriptors that are most important not to
84 // inherit are not the ones that can take an arbitrarily long time
85 // to create: pipe returns instantly, and the net package uses
86 // non-blocking I/O to accept on a listening socket.
87 // The rules for which file descriptor-creating operations use the
88 // ForkLock are as follows:
90 // 1) Pipe. Does not block. Use the ForkLock.
91 // 2) Socket. Does not block. Use the ForkLock.
92 // 3) Accept. If using non-blocking mode, use the ForkLock.
93 // Otherwise, live with the race.
94 // 4) Open. Can block. Use O_CLOEXEC if available (GNU/Linux).
95 // Otherwise, live with the race.
96 // 5) Dup. Does not block. Use the ForkLock.
97 // On GNU/Linux, could use fcntl F_DUPFD_CLOEXEC
98 // instead of the ForkLock, but only for dup(fd, -1).
100 var ForkLock sync
.RWMutex
102 // StringSlicePtr is deprecated. Use SlicePtrFromStrings instead.
103 // If any string contains a NUL byte this function panics instead
104 // of returning an error.
105 func StringSlicePtr(ss
[]string) []*byte {
106 bb
:= make([]*byte, len(ss
)+1)
107 for i
:= 0; i
< len(ss
); i
++ {
108 bb
[i
] = StringBytePtr(ss
[i
])
114 // SlicePtrFromStrings converts a slice of strings to a slice of
115 // pointers to NUL-terminated byte slices. If any string contains
116 // a NUL byte, it returns (nil, EINVAL).
117 func SlicePtrFromStrings(ss
[]string) ([]*byte, error
) {
119 bb
:= make([]*byte, len(ss
)+1)
120 for i
:= 0; i
< len(ss
); i
++ {
121 bb
[i
], err
= BytePtrFromString(ss
[i
])
130 func CloseOnExec(fd
int) { fcntl(fd
, F_SETFD
, FD_CLOEXEC
) }
132 func SetNonblock(fd
int, nonblocking
bool) (err error
) {
133 flag
, err
:= fcntl(fd
, F_GETFL
, 0)
142 _
, err
= fcntl(fd
, F_SETFL
, flag
)
146 // Credential holds user and group identities to be assumed
147 // by a child process started by StartProcess.
148 type Credential
struct {
149 Uid
uint32 // User ID.
150 Gid
uint32 // Group ID.
151 Groups
[]uint32 // Supplementary group IDs.
154 // ProcAttr holds attributes that will be applied to a new process started
156 type ProcAttr
struct {
157 Dir
string // Current working directory.
158 Env
[]string // Environment.
159 Files
[]uintptr // File descriptors.
163 var zeroProcAttr ProcAttr
164 var zeroSysProcAttr SysProcAttr
166 func forkExec(argv0
string, argv
[]string, attr
*ProcAttr
) (pid
int, err error
) {
170 var wstatus WaitStatus
177 sys
= &zeroSysProcAttr
183 // Convert args to C form.
184 argv0p
, err
:= BytePtrFromString(argv0
)
188 argvp
, err
:= SlicePtrFromStrings(argv
)
192 envvp
, err
:= SlicePtrFromStrings(attr
.Env
)
197 if runtime
.GOOS
== "freebsd" && len(argv
[0]) > len(argv0
) {
202 if sys
.Chroot
!= "" {
203 chroot
, err
= BytePtrFromString(sys
.Chroot
)
210 dir
, err
= BytePtrFromString(attr
.Dir
)
216 // Acquire the fork lock so that no other threads
217 // create new fds that are not yet close-on-exec
221 // Allocate child status pipe close on exec.
222 if err
= forkExecPipe(p
[:]); err
!= nil {
227 pid
, err1
= forkAndExecInChild(argv0p
, argvp
, envvp
, chroot
, dir
, attr
, sys
, p
[1])
233 // Read child error status from pipe.
235 n
, err
= readlen(p
[0], (*byte)(unsafe
.Pointer(&err1
)), int(unsafe
.Sizeof(err1
)))
237 if err
!= nil || n
!= 0 {
238 if n
== int(unsafe
.Sizeof(err1
)) {
245 // Child failed; wait for it to exit, to make sure
246 // the zombies don't accumulate.
247 _
, err1
:= Wait4(pid
, &wstatus
, 0, nil)
249 _
, err1
= Wait4(pid
, &wstatus
, 0, nil)
254 // Read got EOF, so pipe closed on exec, so exec succeeded.
266 // Combination of fork and exec, careful to be thread safe.
267 func ForkExec(argv0
string, argv
[]string, attr
*ProcAttr
) (pid
int, err error
) {
268 return forkExec(argv0
, argv
, attr
)
271 // StartProcess wraps ForkExec for package os.
272 func StartProcess(argv0
string, argv
[]string, attr
*ProcAttr
) (pid
int, handle
uintptr, err error
) {
273 pid
, err
= forkExec(argv0
, argv
, attr
)
278 func Exec(argv0
string, argv
[]string, envv
[]string) (err error
) {
279 argv0p
, err
:= BytePtrFromString(argv0
)
283 argvp
, err
:= SlicePtrFromStrings(argv
)
287 envvp
, err
:= SlicePtrFromStrings(envv
)
291 err1
:= raw_execve(argv0p
, &argvp
[0], &envvp
[0])