Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(3)

Side by Side Diff: unix/exec_linux.go

Issue 126960043: code review 126960043: go.sys: copy files from syscall package to go.sys/{plan... (Closed)
Patch Set: diff -r 89b705e036f489a14b4d11c6e025ea61a53bb735 https://code.google.com/p/go.sys Created 10 years, 7 months ago
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
View unified diff | Download patch
« no previous file with comments | « unix/exec_bsd.go ('k') | unix/exec_solaris.go » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright 2011 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.
4
5 // +build linux
6
7 package syscall
8
9 import (
10 "unsafe"
11 )
12
13 type SysProcAttr struct {
14 Chroot string // Chroot.
15 Credential *Credential // Credential.
16 Ptrace bool // Enable tracing.
17 Setsid bool // Create session.
18 Setpgid bool // Set process group ID to new pid (SYSV setpgrp)
19 Setctty bool // Set controlling terminal to fd Ctty (only mean ingful if Setsid is set)
20 Noctty bool // Detach fd 0 from controlling terminal
21 Ctty int // Controlling TTY fd (Linux only)
22 Pdeathsig Signal // Signal that the process will get when its pare nt dies (Linux only)
23 Cloneflags uintptr // Flags for clone calls (Linux only)
24 }
25
26 // Implemented in runtime package.
27 func runtime_BeforeFork()
28 func runtime_AfterFork()
29
30 // Fork, dup fd onto 0..len(fd), and exec(argv0, argvv, envv) in child.
31 // If a dup or exec fails, write the errno error to pipe.
32 // (Pipe is close-on-exec so if exec succeeds, it will be closed.)
33 // In the child, this function must not acquire any locks, because
34 // they might have been locked at the time of the fork. This means
35 // no rescheduling, no malloc calls, and no new stack segments.
36 // For the same reason compiler does not race instrument it.
37 // The calls to RawSyscall are okay because they are assembly
38 // functions that do not grow the stack.
39 func forkAndExecInChild(argv0 *byte, argv, envv []*byte, chroot, dir *byte, attr *ProcAttr, sys *SysProcAttr, pipe int) (pid int, err Errno) {
40 // Declare all variables at top in case any
41 // declarations require heap allocation (e.g., err1).
42 var (
43 r1 uintptr
44 err1 Errno
45 nextfd int
46 i int
47 )
48
49 // Guard against side effects of shuffling fds below.
50 // Make sure that nextfd is beyond any currently open files so
51 // that we can't run the risk of overwriting any of them.
52 fd := make([]int, len(attr.Files))
53 nextfd = len(attr.Files)
54 for i, ufd := range attr.Files {
55 if nextfd < int(ufd) {
56 nextfd = int(ufd)
57 }
58 fd[i] = int(ufd)
59 }
60 nextfd++
61
62 // About to call fork.
63 // No more allocation or calls of non-assembly functions.
64 runtime_BeforeFork()
65 r1, _, err1 = RawSyscall6(SYS_CLONE, uintptr(SIGCHLD)|sys.Cloneflags, 0, 0, 0, 0, 0)
66 if err1 != 0 {
67 runtime_AfterFork()
68 return 0, err1
69 }
70
71 if r1 != 0 {
72 // parent; return PID
73 runtime_AfterFork()
74 return int(r1), 0
75 }
76
77 // Fork succeeded, now in child.
78
79 // Parent death signal
80 if sys.Pdeathsig != 0 {
81 _, _, err1 = RawSyscall6(SYS_PRCTL, PR_SET_PDEATHSIG, uintptr(sy s.Pdeathsig), 0, 0, 0, 0)
82 if err1 != 0 {
83 goto childerror
84 }
85
86 // Signal self if parent is already dead. This might cause a
87 // duplicate signal in rare cases, but it won't matter when
88 // using SIGKILL.
89 r1, _, _ = RawSyscall(SYS_GETPPID, 0, 0, 0)
90 if r1 == 1 {
91 pid, _, _ := RawSyscall(SYS_GETPID, 0, 0, 0)
92 _, _, err1 := RawSyscall(SYS_KILL, pid, uintptr(sys.Pdea thsig), 0)
93 if err1 != 0 {
94 goto childerror
95 }
96 }
97 }
98
99 // Enable tracing if requested.
100 if sys.Ptrace {
101 _, _, err1 = RawSyscall(SYS_PTRACE, uintptr(PTRACE_TRACEME), 0, 0)
102 if err1 != 0 {
103 goto childerror
104 }
105 }
106
107 // Session ID
108 if sys.Setsid {
109 _, _, err1 = RawSyscall(SYS_SETSID, 0, 0, 0)
110 if err1 != 0 {
111 goto childerror
112 }
113 }
114
115 // Set process group
116 if sys.Setpgid {
117 _, _, err1 = RawSyscall(SYS_SETPGID, 0, 0, 0)
118 if err1 != 0 {
119 goto childerror
120 }
121 }
122
123 // Chroot
124 if chroot != nil {
125 _, _, err1 = RawSyscall(SYS_CHROOT, uintptr(unsafe.Pointer(chroo t)), 0, 0)
126 if err1 != 0 {
127 goto childerror
128 }
129 }
130
131 // User and groups
132 if cred := sys.Credential; cred != nil {
133 ngroups := uintptr(len(cred.Groups))
134 var groups unsafe.Pointer
135 if ngroups > 0 {
136 groups = unsafe.Pointer(&cred.Groups[0])
137 }
138 _, _, err1 = RawSyscall(SYS_SETGROUPS, ngroups, uintptr(groups), 0)
139 if err1 != 0 {
140 goto childerror
141 }
142 _, _, err1 = RawSyscall(SYS_SETGID, uintptr(cred.Gid), 0, 0)
143 if err1 != 0 {
144 goto childerror
145 }
146 _, _, err1 = RawSyscall(SYS_SETUID, uintptr(cred.Uid), 0, 0)
147 if err1 != 0 {
148 goto childerror
149 }
150 }
151
152 // Chdir
153 if dir != nil {
154 _, _, err1 = RawSyscall(SYS_CHDIR, uintptr(unsafe.Pointer(dir)), 0, 0)
155 if err1 != 0 {
156 goto childerror
157 }
158 }
159
160 // Pass 1: look for fd[i] < i and move those up above len(fd)
161 // so that pass 2 won't stomp on an fd it needs later.
162 if pipe < nextfd {
163 _, _, err1 = RawSyscall(SYS_DUP2, uintptr(pipe), uintptr(nextfd) , 0)
164 if err1 != 0 {
165 goto childerror
166 }
167 RawSyscall(SYS_FCNTL, uintptr(nextfd), F_SETFD, FD_CLOEXEC)
168 pipe = nextfd
169 nextfd++
170 }
171 for i = 0; i < len(fd); i++ {
172 if fd[i] >= 0 && fd[i] < int(i) {
173 _, _, err1 = RawSyscall(SYS_DUP2, uintptr(fd[i]), uintpt r(nextfd), 0)
174 if err1 != 0 {
175 goto childerror
176 }
177 RawSyscall(SYS_FCNTL, uintptr(nextfd), F_SETFD, FD_CLOEX EC)
178 fd[i] = nextfd
179 nextfd++
180 if nextfd == pipe { // don't stomp on pipe
181 nextfd++
182 }
183 }
184 }
185
186 // Pass 2: dup fd[i] down onto i.
187 for i = 0; i < len(fd); i++ {
188 if fd[i] == -1 {
189 RawSyscall(SYS_CLOSE, uintptr(i), 0, 0)
190 continue
191 }
192 if fd[i] == int(i) {
193 // dup2(i, i) won't clear close-on-exec flag on Linux,
194 // probably not elsewhere either.
195 _, _, err1 = RawSyscall(SYS_FCNTL, uintptr(fd[i]), F_SET FD, 0)
196 if err1 != 0 {
197 goto childerror
198 }
199 continue
200 }
201 // The new fd is created NOT close-on-exec,
202 // which is exactly what we want.
203 _, _, err1 = RawSyscall(SYS_DUP2, uintptr(fd[i]), uintptr(i), 0)
204 if err1 != 0 {
205 goto childerror
206 }
207 }
208
209 // By convention, we don't close-on-exec the fds we are
210 // started with, so if len(fd) < 3, close 0, 1, 2 as needed.
211 // Programs that know they inherit fds >= 3 will need
212 // to set them close-on-exec.
213 for i = len(fd); i < 3; i++ {
214 RawSyscall(SYS_CLOSE, uintptr(i), 0, 0)
215 }
216
217 // Detach fd 0 from tty
218 if sys.Noctty {
219 _, _, err1 = RawSyscall(SYS_IOCTL, 0, uintptr(TIOCNOTTY), 0)
220 if err1 != 0 {
221 goto childerror
222 }
223 }
224
225 // Set the controlling TTY to Ctty
226 if sys.Setctty && sys.Ctty >= 0 {
227 _, _, err1 = RawSyscall(SYS_IOCTL, uintptr(sys.Ctty), uintptr(TI OCSCTTY), 0)
228 if err1 != 0 {
229 goto childerror
230 }
231 }
232
233 // Time to exec.
234 _, _, err1 = RawSyscall(SYS_EXECVE,
235 uintptr(unsafe.Pointer(argv0)),
236 uintptr(unsafe.Pointer(&argv[0])),
237 uintptr(unsafe.Pointer(&envv[0])))
238
239 childerror:
240 // send error code on pipe
241 RawSyscall(SYS_WRITE, uintptr(pipe), uintptr(unsafe.Pointer(&err1)), uns afe.Sizeof(err1))
242 for {
243 RawSyscall(SYS_EXIT, 253, 0, 0)
244 }
245 }
246
247 // Try to open a pipe with O_CLOEXEC set on both file descriptors.
248 func forkExecPipe(p []int) (err error) {
249 err = Pipe2(p, O_CLOEXEC)
250 // pipe2 was added in 2.6.27 and our minimum requirement is 2.6.23, so i t
251 // might not be implemented.
252 if err == ENOSYS {
253 if err = Pipe(p); err != nil {
254 return
255 }
256 if _, err = fcntl(p[0], F_SETFD, FD_CLOEXEC); err != nil {
257 return
258 }
259 _, err = fcntl(p[1], F_SETFD, FD_CLOEXEC)
260 }
261 return
262 }
OLDNEW
« no previous file with comments | « unix/exec_bsd.go ('k') | unix/exec_solaris.go » ('j') | no next file with comments »

Powered by Google App Engine
RSS Feeds Recent Issues | This issue
This is Rietveld f62528b