Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(651)

Side by Side Diff: fusl/src/process/posix_spawn.c

Issue 1714623002: [fusl] clang-format fusl (Closed) Base URL: git@github.com:domokit/mojo.git@master
Patch Set: headers too Created 4 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 #define _GNU_SOURCE 1 #define _GNU_SOURCE
2 #include <spawn.h> 2 #include <spawn.h>
3 #include <sched.h> 3 #include <sched.h>
4 #include <unistd.h> 4 #include <unistd.h>
5 #include <signal.h> 5 #include <signal.h>
6 #include <fcntl.h> 6 #include <fcntl.h>
7 #include <sys/wait.h> 7 #include <sys/wait.h>
8 #include "syscall.h" 8 #include "syscall.h"
9 #include "pthread_impl.h" 9 #include "pthread_impl.h"
10 #include "fdop.h" 10 #include "fdop.h"
11 #include "libc.h" 11 #include "libc.h"
12 12
13 struct args { 13 struct args {
14 » int p[2]; 14 int p[2];
15 » sigset_t oldmask; 15 sigset_t oldmask;
16 » const char *path; 16 const char* path;
17 » int (*exec)(const char *, char *const *, char *const *); 17 int (*exec)(const char*, char* const*, char* const*);
18 » const posix_spawn_file_actions_t *fa; 18 const posix_spawn_file_actions_t* fa;
19 » const posix_spawnattr_t *restrict attr; 19 const posix_spawnattr_t* restrict attr;
20 » char *const *argv, *const *envp; 20 char *const *argv, *const *envp;
21 }; 21 };
22 22
23 void __get_handler_set(sigset_t *); 23 void __get_handler_set(sigset_t*);
24 24
25 static int __sys_dup2(int old, int new) 25 static int __sys_dup2(int old, int new) {
26 {
27 #ifdef SYS_dup2 26 #ifdef SYS_dup2
28 » return __syscall(SYS_dup2, old, new); 27 return __syscall(SYS_dup2, old, new);
29 #else 28 #else
30 » if (old==new) { 29 if (old == new) {
31 » » int r = __syscall(SYS_fcntl, old, F_GETFD); 30 int r = __syscall(SYS_fcntl, old, F_GETFD);
32 » » return r<0 ? r : old; 31 return r < 0 ? r : old;
33 » } else { 32 } else {
34 » » return __syscall(SYS_dup3, old, new, 0); 33 return __syscall(SYS_dup3, old, new, 0);
35 » } 34 }
36 #endif 35 #endif
37 } 36 }
38 37
39 static int child(void *args_vp) 38 static int child(void* args_vp) {
40 { 39 int i, ret;
41 » int i, ret; 40 struct sigaction sa = {0};
42 » struct sigaction sa = {0}; 41 struct args* args = args_vp;
43 » struct args *args = args_vp; 42 int p = args->p[1];
44 » int p = args->p[1]; 43 const posix_spawn_file_actions_t* fa = args->fa;
45 » const posix_spawn_file_actions_t *fa = args->fa; 44 const posix_spawnattr_t* restrict attr = args->attr;
46 » const posix_spawnattr_t *restrict attr = args->attr; 45 sigset_t hset;
47 » sigset_t hset;
48 46
49 » close(args->p[0]); 47 close(args->p[0]);
50 48
51 » /* All signal dispositions must be either SIG_DFL or SIG_IGN 49 /* All signal dispositions must be either SIG_DFL or SIG_IGN
52 » * before signals are unblocked. Otherwise a signal handler 50 * before signals are unblocked. Otherwise a signal handler
53 » * from the parent might get run in the child while sharing 51 * from the parent might get run in the child while sharing
54 » * memory, with unpredictable and dangerous results. To 52 * memory, with unpredictable and dangerous results. To
55 » * reduce overhead, sigaction has tracked for us which signals 53 * reduce overhead, sigaction has tracked for us which signals
56 » * potentially have a signal handler. */ 54 * potentially have a signal handler. */
57 » __get_handler_set(&hset); 55 __get_handler_set(&hset);
58 » for (i=1; i<_NSIG; i++) { 56 for (i = 1; i < _NSIG; i++) {
59 » » if ((attr->__flags & POSIX_SPAWN_SETSIGDEF) 57 if ((attr->__flags & POSIX_SPAWN_SETSIGDEF) &&
60 » » && sigismember(&attr->__def, i)) { 58 sigismember(&attr->__def, i)) {
61 » » » sa.sa_handler = SIG_DFL; 59 sa.sa_handler = SIG_DFL;
62 » » } else if (sigismember(&hset, i)) { 60 } else if (sigismember(&hset, i)) {
63 » » » if (i-32<3U) { 61 if (i - 32 < 3U) {
64 » » » » sa.sa_handler = SIG_IGN; 62 sa.sa_handler = SIG_IGN;
65 » » » } else { 63 } else {
66 » » » » __libc_sigaction(i, 0, &sa); 64 __libc_sigaction(i, 0, &sa);
67 » » » » if (sa.sa_handler==SIG_IGN) continue; 65 if (sa.sa_handler == SIG_IGN)
68 » » » » sa.sa_handler = SIG_DFL; 66 continue;
69 » » » } 67 sa.sa_handler = SIG_DFL;
70 » » } else { 68 }
71 » » » continue; 69 } else {
72 » » } 70 continue;
73 » » __libc_sigaction(i, &sa, 0); 71 }
74 » } 72 __libc_sigaction(i, &sa, 0);
73 }
75 74
76 » if (attr->__flags & POSIX_SPAWN_SETPGROUP) 75 if (attr->__flags & POSIX_SPAWN_SETPGROUP)
77 » » if ((ret=__syscall(SYS_setpgid, 0, attr->__pgrp))) 76 if ((ret = __syscall(SYS_setpgid, 0, attr->__pgrp)))
78 » » » goto fail; 77 goto fail;
79 78
80 » /* Use syscalls directly because the library functions attempt 79 /* Use syscalls directly because the library functions attempt
81 » * to do a multi-threaded synchronized id-change, which would 80 * to do a multi-threaded synchronized id-change, which would
82 » * trash the parent's state. */ 81 * trash the parent's state. */
83 » if (attr->__flags & POSIX_SPAWN_RESETIDS) 82 if (attr->__flags & POSIX_SPAWN_RESETIDS)
84 » » if ((ret=__syscall(SYS_setgid, __syscall(SYS_getgid))) || 83 if ((ret = __syscall(SYS_setgid, __syscall(SYS_getgid))) ||
85 » » (ret=__syscall(SYS_setuid, __syscall(SYS_getuid))) ) 84 (ret = __syscall(SYS_setuid, __syscall(SYS_getuid))))
86 » » » goto fail; 85 goto fail;
87 86
88 » if (fa && fa->__actions) { 87 if (fa && fa->__actions) {
89 » » struct fdop *op; 88 struct fdop* op;
90 » » int fd; 89 int fd;
91 » » for (op = fa->__actions; op->next; op = op->next); 90 for (op = fa->__actions; op->next; op = op->next)
92 » » for (; op; op = op->prev) { 91 ;
93 » » » /* It's possible that a file operation would clobber 92 for (; op; op = op->prev) {
94 » » » * the pipe fd used for synchronizing with the 93 /* It's possible that a file operation would clobber
95 » » » * parent. To avoid that, we dup the pipe onto 94 * the pipe fd used for synchronizing with the
96 » » » * an unoccupied fd. */ 95 * parent. To avoid that, we dup the pipe onto
97 » » » if (op->fd == p) { 96 * an unoccupied fd. */
98 » » » » ret = __syscall(SYS_dup, p); 97 if (op->fd == p) {
99 » » » » if (ret < 0) goto fail; 98 ret = __syscall(SYS_dup, p);
100 » » » » __syscall(SYS_close, p); 99 if (ret < 0)
101 » » » » p = ret; 100 goto fail;
102 » » » } 101 __syscall(SYS_close, p);
103 » » » switch(op->cmd) { 102 p = ret;
104 » » » case FDOP_CLOSE: 103 }
105 » » » » __syscall(SYS_close, op->fd); 104 switch (op->cmd) {
106 » » » » break; 105 case FDOP_CLOSE:
107 » » » case FDOP_DUP2: 106 __syscall(SYS_close, op->fd);
108 » » » » if ((ret=__sys_dup2(op->srcfd, op->fd))<0) 107 break;
109 » » » » » goto fail; 108 case FDOP_DUP2:
110 » » » » break; 109 if ((ret = __sys_dup2(op->srcfd, op->fd)) < 0)
111 » » » case FDOP_OPEN: 110 goto fail;
112 » » » » fd = __sys_open(op->path, op->oflag, op->mode); 111 break;
113 » » » » if ((ret=fd) < 0) goto fail; 112 case FDOP_OPEN:
114 » » » » if (fd != op->fd) { 113 fd = __sys_open(op->path, op->oflag, op->mode);
115 » » » » » if ((ret=__sys_dup2(fd, op->fd))<0) 114 if ((ret = fd) < 0)
116 » » » » » » goto fail; 115 goto fail;
117 » » » » » __syscall(SYS_close, fd); 116 if (fd != op->fd) {
118 » » » » } 117 if ((ret = __sys_dup2(fd, op->fd)) < 0)
119 » » » » break; 118 goto fail;
120 » » » } 119 __syscall(SYS_close, fd);
121 » » } 120 }
122 » } 121 break;
122 }
123 }
124 }
123 125
124 » /* Close-on-exec flag may have been lost if we moved the pipe 126 /* Close-on-exec flag may have been lost if we moved the pipe
125 » * to a different fd. We don't use F_DUPFD_CLOEXEC above because 127 * to a different fd. We don't use F_DUPFD_CLOEXEC above because
126 » * it would fail on older kernels and atomicity is not needed -- 128 * it would fail on older kernels and atomicity is not needed --
127 » * in this process there are no threads or signal handlers. */ 129 * in this process there are no threads or signal handlers. */
128 » __syscall(SYS_fcntl, p, F_SETFD, FD_CLOEXEC); 130 __syscall(SYS_fcntl, p, F_SETFD, FD_CLOEXEC);
129 131
130 » pthread_sigmask(SIG_SETMASK, (attr->__flags & POSIX_SPAWN_SETSIGMASK) 132 pthread_sigmask(
131 » » ? &attr->__mask : &args->oldmask, 0); 133 SIG_SETMASK,
134 (attr->__flags & POSIX_SPAWN_SETSIGMASK) ? &attr->__mask : &args->oldmask,
135 0);
132 136
133 » args->exec(args->path, args->argv, args->envp); 137 args->exec(args->path, args->argv, args->envp);
134 » ret = -errno; 138 ret = -errno;
135 139
136 fail: 140 fail:
137 » /* Since sizeof errno < PIPE_BUF, the write is atomic. */ 141 /* Since sizeof errno < PIPE_BUF, the write is atomic. */
138 » ret = -ret; 142 ret = -ret;
139 » if (ret) while (__syscall(SYS_write, p, &ret, sizeof ret) < 0); 143 if (ret)
140 » _exit(127); 144 while (__syscall(SYS_write, p, &ret, sizeof ret) < 0)
145 ;
146 _exit(127);
141 } 147 }
142 148
149 int __posix_spawnx(pid_t* restrict res,
150 const char* restrict path,
151 int (*exec)(const char*, char* const*, char* const*),
152 const posix_spawn_file_actions_t* fa,
153 const posix_spawnattr_t* restrict attr,
154 char* const argv[restrict],
155 char* const envp[restrict]) {
156 pid_t pid;
157 char stack[1024];
158 int ec = 0, cs;
159 struct args args;
143 160
144 int __posix_spawnx(pid_t *restrict res, const char *restrict path, 161 if (pipe2(args.p, O_CLOEXEC))
145 » int (*exec)(const char *, char *const *, char *const *), 162 return errno;
146 » const posix_spawn_file_actions_t *fa,
147 » const posix_spawnattr_t *restrict attr,
148 » char *const argv[restrict], char *const envp[restrict])
149 {
150 » pid_t pid;
151 » char stack[1024];
152 » int ec=0, cs;
153 » struct args args;
154 163
155 » if (pipe2(args.p, O_CLOEXEC)) 164 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cs);
156 » » return errno;
157 165
158 » pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cs); 166 args.path = path;
167 args.exec = exec;
168 args.fa = fa;
169 args.attr = attr ? attr : &(const posix_spawnattr_t){0};
170 args.argv = argv;
171 args.envp = envp;
172 pthread_sigmask(SIG_BLOCK, SIGALL_SET, &args.oldmask);
159 173
160 » args.path = path; 174 pid = __clone(child, stack + sizeof stack, CLONE_VM | CLONE_VFORK | SIGCHLD,
161 » args.exec = exec; 175 &args);
162 » args.fa = fa; 176 close(args.p[1]);
163 » args.attr = attr ? attr : &(const posix_spawnattr_t){0};
164 » args.argv = argv;
165 » args.envp = envp;
166 » pthread_sigmask(SIG_BLOCK, SIGALL_SET, &args.oldmask);
167 177
168 » pid = __clone(child, stack+sizeof stack, 178 if (pid > 0) {
169 » » CLONE_VM|CLONE_VFORK|SIGCHLD, &args); 179 if (read(args.p[0], &ec, sizeof ec) != sizeof ec)
170 » close(args.p[1]); 180 ec = 0;
181 else
182 waitpid(pid, &(int){0}, 0);
183 } else {
184 ec = -pid;
185 }
171 186
172 » if (pid > 0) { 187 close(args.p[0]);
173 » » if (read(args.p[0], &ec, sizeof ec) != sizeof ec) ec = 0;
174 » » else waitpid(pid, &(int){0}, 0);
175 » } else {
176 » » ec = -pid;
177 » }
178 188
179 » close(args.p[0]); 189 if (!ec && res)
190 *res = pid;
180 191
181 » if (!ec && res) *res = pid; 192 pthread_sigmask(SIG_SETMASK, &args.oldmask, 0);
193 pthread_setcancelstate(cs, 0);
182 194
183 » pthread_sigmask(SIG_SETMASK, &args.oldmask, 0); 195 return ec;
184 » pthread_setcancelstate(cs, 0);
185
186 » return ec;
187 } 196 }
188 197
189 int posix_spawn(pid_t *restrict res, const char *restrict path, 198 int posix_spawn(pid_t* restrict res,
190 » const posix_spawn_file_actions_t *fa, 199 const char* restrict path,
191 » const posix_spawnattr_t *restrict attr, 200 const posix_spawn_file_actions_t* fa,
192 » char *const argv[restrict], char *const envp[restrict]) 201 const posix_spawnattr_t* restrict attr,
193 { 202 char* const argv[restrict],
194 » return __posix_spawnx(res, path, execve, fa, attr, argv, envp); 203 char* const envp[restrict]) {
204 return __posix_spawnx(res, path, execve, fa, attr, argv, envp);
195 } 205 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698