|
8 | 8 | #include <unistd.h>
|
9 | 9 | #include <errno.h>
|
10 | 10 | #include <sched.h>
|
| 11 | +#include <pthread.h> |
11 | 12 | #include <linux/limits.h>
|
12 | 13 | #include <sys/socket.h>
|
13 | 14 | #include <sys/wait.h>
|
@@ -167,3 +168,65 @@ int helper_wait(int pid)
|
167 | 168 | } else
|
168 | 169 | return 0;
|
169 | 170 | }
|
| 171 | + |
| 172 | +struct os_helper_thread { |
| 173 | + pthread_t handle; |
| 174 | +}; |
| 175 | + |
| 176 | +int os_run_helper_thread(struct os_helper_thread **td_out, |
| 177 | + void *(*routine)(void *), void *arg) |
| 178 | +{ |
| 179 | + struct os_helper_thread *td; |
| 180 | + sigset_t sigset, oset; |
| 181 | + int err, flags; |
| 182 | + |
| 183 | + flags = __uml_cant_sleep() ? UM_GFP_ATOMIC : UM_GFP_KERNEL; |
| 184 | + td = uml_kmalloc(sizeof(*td), flags); |
| 185 | + if (!td) |
| 186 | + return -ENOMEM; |
| 187 | + |
| 188 | + sigfillset(&sigset); |
| 189 | + if (sigprocmask(SIG_SETMASK, &sigset, &oset) < 0) { |
| 190 | + err = -errno; |
| 191 | + kfree(td); |
| 192 | + return err; |
| 193 | + } |
| 194 | + |
| 195 | + err = pthread_create(&td->handle, NULL, routine, arg); |
| 196 | + |
| 197 | + if (sigprocmask(SIG_SETMASK, &oset, NULL) < 0) |
| 198 | + panic("Failed to restore the signal mask: %d", errno); |
| 199 | + |
| 200 | + if (err != 0) |
| 201 | + kfree(td); |
| 202 | + else |
| 203 | + *td_out = td; |
| 204 | + |
| 205 | + return -err; |
| 206 | +} |
| 207 | + |
| 208 | +void os_kill_helper_thread(struct os_helper_thread *td) |
| 209 | +{ |
| 210 | + pthread_cancel(td->handle); |
| 211 | + pthread_join(td->handle, NULL); |
| 212 | + kfree(td); |
| 213 | +} |
| 214 | + |
| 215 | +void os_fix_helper_thread_signals(void) |
| 216 | +{ |
| 217 | + sigset_t sigset; |
| 218 | + |
| 219 | + sigemptyset(&sigset); |
| 220 | + |
| 221 | + sigaddset(&sigset, SIGWINCH); |
| 222 | + sigaddset(&sigset, SIGPIPE); |
| 223 | + sigaddset(&sigset, SIGPROF); |
| 224 | + sigaddset(&sigset, SIGINT); |
| 225 | + sigaddset(&sigset, SIGTERM); |
| 226 | + sigaddset(&sigset, SIGCHLD); |
| 227 | + sigaddset(&sigset, SIGALRM); |
| 228 | + sigaddset(&sigset, SIGIO); |
| 229 | + sigaddset(&sigset, SIGUSR1); |
| 230 | + |
| 231 | + pthread_sigmask(SIG_SETMASK, &sigset, NULL); |
| 232 | +} |
0 commit comments