1 // exec.go -- fork/exec syscall support.
3 // Copyright 2009 The Go Authors. All rights reserved.
4 // Use of this source code is governed by a BSD-style
5 // license that can be found in the LICENSE file.
7 // Fork, exec, wait, etc.
13 func libc_fcntl(fd int, cmd int, arg int) int __asm__ ("fcntl")
14 func libc_fork() Pid_t __asm__ ("fork")
15 func libc_chdir(name *byte) int __asm__ ("chdir");
16 func libc_dup2(int, int) int __asm__ ("dup2")
17 func libc_execve(*byte, **byte, **byte) int __asm__ ("execve")
18 func libc_sysexit(int) __asm__ ("_exit")
19 func libc_wait4(Pid_t, *int, int, *Rusage) Pid_t __asm__ ("wait4")
21 // Fork, dup fd onto 0..len(fd), and exec(argv0, argvv, envv) in child.
22 // If a dup or exec fails, write the errno int to pipe.
23 // (Pipe is close-on-exec so if exec succeeds, it will be closed.)
24 // In the child, this function must not acquire any locks, because
25 // they might have been locked at the time of the fork. This means
26 // no rescheduling, no malloc calls, and no new stack segments.
27 func forkAndExecInChild(argv0 *byte, argv []*byte, envv []*byte, traceme bool, dir *byte, fd []int, pipe int) (pid int, err int) {
28 // Declare all variables at top in case any
29 // declarations require heap allocation (e.g., err1).
30 var r1, r2, err1 uintptr;
34 darwin := OS == "darwin";
36 // About to call fork.
37 // No more allocation or calls of non-assembly functions.
48 // Fork succeeded, now in child.
50 // Enable tracing if requested.
52 if libc_ptrace(_PTRACE_TRACEME, 0, 0, nil) < 0 {
65 // Pass 1: look for fd[i] < i and move those up above len(fd)
66 // so that pass 2 won't stomp on an fd it needs later.
67 nextfd = int(len(fd));
69 r := libc_dup2(pipe, nextfd);
73 libc_fcntl(nextfd, F_SETFD, FD_CLOEXEC);
77 for i = 0; i < len(fd); i++ {
78 if fd[i] >= 0 && fd[i] < int(i) {
79 r := libc_dup2(fd[i], nextfd);
83 libc_fcntl(nextfd, F_SETFD, FD_CLOEXEC);
86 if nextfd == pipe { // don't stomp on pipe
92 // Pass 2: dup fd[i] down onto i.
93 for i = 0; i < len(fd); i++ {
99 // dup2(i, i) won't clear close-on-exec flag on Linux,
100 // probably not elsewhere either.
101 r := libc_fcntl(fd[i], F_SETFD, 0);
107 // The new fd is created NOT close-on-exec,
108 // which is exactly what we want.
109 r := libc_dup2(fd[i], i);
115 // By convention, we don't close-on-exec the fds we are
116 // started with, so if len(fd) < 3, close 0, 1, 2 as needed.
117 // Programs that know they inherit fds >= 3 will need
118 // to set them close-on-exec.
119 for i = len(fd); i < 3; i++ {
124 libc_execve(argv0, &argv[0], &envv[0]);
127 // send error code on pipe
128 var e uintptr = uintptr(GetErrno());
129 libc_write(pipe, (*byte)(unsafe.Pointer(&e)),
130 Size_t(unsafe.Sizeof(err1)));
135 // Calling panic is not actually safe,
136 // but the for loop above won't break
137 // and this shuts up the compiler.
141 func forkExec(argv0 string, argv []string, envv []string, traceme bool, dir string, fd []int) (pid int, err int) {
145 var wstatus WaitStatus;
150 // Convert args to C form.
151 argv0p := StringBytePtr(argv0);
152 argvp := StringArrayPtr(argv);
153 envvp := StringArrayPtr(envv);
156 dirp = StringBytePtr(dir);
159 // Acquire the fork lock so that no other threads
160 // create new fds that are not yet close-on-exec
164 // Allocate child status pipe close on exec.
165 if err = Pipe(p[0:]); err != 0 {
169 if val, err = fcntl(p[0], F_SETFD, FD_CLOEXEC); err != 0 {
172 if val, err = fcntl(p[1], F_SETFD, FD_CLOEXEC); err != 0 {
177 pid, err = forkAndExecInChild(argv0p, argvp, envvp, traceme, dirp, fd, p[1]);
189 // Read child error status from pipe.
191 n := libc_read(p[0], (*byte)(unsafe.Pointer(&err1)),
192 Size_t(unsafe.Sizeof(err1)));
198 if err != 0 || n != 0 {
199 if int(n) == unsafe.Sizeof(err1) {
206 // Child failed; wait for it to exit, to make sure
207 // the zombies don't accumulate.
208 pid1, err1 := Wait4(pid, &wstatus, 0, nil);
210 pid1, err1 = Wait4(pid, &wstatus, 0, nil);
215 // Read got EOF, so pipe closed on exec, so exec succeeded.
219 // Combination of fork and exec, careful to be thread safe.
220 func ForkExec(argv0 string, argv []string, envv []string, dir string, fd []int) (pid int, err int) {
221 return forkExec(argv0, argv, envv, false, dir, fd);
224 // PtraceForkExec is like ForkExec, but starts the child in a traced state.
225 func PtraceForkExec(argv0 string, argv []string, envv []string, dir string, fd []int) (pid int, err int) {
226 return forkExec(argv0, argv, envv, true, dir, fd);
230 func Exec(argv0 string, argv []string, envv []string) (err int) {
231 argv_arg := StringArrayPtr(argv);
232 envv_arg := StringArrayPtr(envv);
233 libc_execve(StringBytePtr(argv0), &argv_arg[0], &envv_arg[0]);
237 func Wait4(pid int, wstatus *WaitStatus, options int, rusage *Rusage) (wpid int, errno int) {
239 r := libc_wait4(Pid_t(pid), &status, options, rusage);
245 *wstatus = WaitStatus(status);