diff options
Diffstat (limited to 'arch/um/os-Linux/helper.c')
-rw-r--r-- | arch/um/os-Linux/helper.c | 74 |
1 files changed, 30 insertions, 44 deletions
diff --git a/arch/um/os-Linux/helper.c b/arch/um/os-Linux/helper.c index fba3f0fefeef..f4bd349d4412 100644 --- a/arch/um/os-Linux/helper.c +++ b/arch/um/os-Linux/helper.c | |||
@@ -1,22 +1,19 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) | 2 | * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) |
3 | * Licensed under the GPL | 3 | * Licensed under the GPL |
4 | */ | 4 | */ |
5 | 5 | ||
6 | #include <stdio.h> | ||
7 | #include <stdlib.h> | 6 | #include <stdlib.h> |
8 | #include <unistd.h> | 7 | #include <unistd.h> |
9 | #include <errno.h> | 8 | #include <errno.h> |
10 | #include <sched.h> | 9 | #include <sched.h> |
11 | #include <limits.h> | ||
12 | #include <sys/signal.h> | ||
13 | #include <sys/wait.h> | ||
14 | #include <sys/socket.h> | 10 | #include <sys/socket.h> |
15 | #include "user.h" | 11 | #include <sys/wait.h> |
12 | #include "kern_constants.h" | ||
16 | #include "kern_util.h" | 13 | #include "kern_util.h" |
17 | #include "os.h" | 14 | #include "os.h" |
18 | #include "um_malloc.h" | 15 | #include "um_malloc.h" |
19 | #include "kern_constants.h" | 16 | #include "user.h" |
20 | 17 | ||
21 | struct helper_data { | 18 | struct helper_data { |
22 | void (*pre_exec)(void*); | 19 | void (*pre_exec)(void*); |
@@ -30,21 +27,19 @@ static int helper_child(void *arg) | |||
30 | { | 27 | { |
31 | struct helper_data *data = arg; | 28 | struct helper_data *data = arg; |
32 | char **argv = data->argv; | 29 | char **argv = data->argv; |
33 | int errval; | 30 | int err; |
34 | 31 | ||
35 | if (data->pre_exec != NULL) | 32 | if (data->pre_exec != NULL) |
36 | (*data->pre_exec)(data->pre_data); | 33 | (*data->pre_exec)(data->pre_data); |
37 | errval = execvp_noalloc(data->buf, argv[0], argv); | 34 | err = execvp_noalloc(data->buf, argv[0], argv); |
38 | printk("helper_child - execvp of '%s' failed - errno = %d\n", argv[0], | 35 | |
39 | -errval); | 36 | /* If the exec succeeds, we don't get here */ |
40 | write(data->fd, &errval, sizeof(errval)); | 37 | write(data->fd, &err, sizeof(err)); |
41 | kill(os_getpid(), SIGKILL); | 38 | |
42 | return 0; | 39 | return 0; |
43 | } | 40 | } |
44 | 41 | ||
45 | /* Returns either the pid of the child process we run or -E* on failure. | 42 | /* Returns either the pid of the child process we run or -E* on failure. */ |
46 | * XXX The alloc_stack here breaks if this is called in the tracing thread, so | ||
47 | * we need to receive a preallocated stack (a local buffer is ok). */ | ||
48 | int run_helper(void (*pre_exec)(void *), void *pre_data, char **argv) | 43 | int run_helper(void (*pre_exec)(void *), void *pre_data, char **argv) |
49 | { | 44 | { |
50 | struct helper_data data; | 45 | struct helper_data data; |
@@ -58,14 +53,15 @@ int run_helper(void (*pre_exec)(void *), void *pre_data, char **argv) | |||
58 | ret = socketpair(AF_UNIX, SOCK_STREAM, 0, fds); | 53 | ret = socketpair(AF_UNIX, SOCK_STREAM, 0, fds); |
59 | if (ret < 0) { | 54 | if (ret < 0) { |
60 | ret = -errno; | 55 | ret = -errno; |
61 | printk("run_helper : pipe failed, errno = %d\n", errno); | 56 | printk(UM_KERN_ERR "run_helper : pipe failed, errno = %d\n", |
57 | errno); | ||
62 | goto out_free; | 58 | goto out_free; |
63 | } | 59 | } |
64 | 60 | ||
65 | ret = os_set_exec_close(fds[1]); | 61 | ret = os_set_exec_close(fds[1]); |
66 | if (ret < 0) { | 62 | if (ret < 0) { |
67 | printk("run_helper : setting FD_CLOEXEC failed, ret = %d\n", | 63 | printk(UM_KERN_ERR "run_helper : setting FD_CLOEXEC failed, " |
68 | -ret); | 64 | "ret = %d\n", -ret); |
69 | goto out_close; | 65 | goto out_close; |
70 | } | 66 | } |
71 | 67 | ||
@@ -79,7 +75,8 @@ int run_helper(void (*pre_exec)(void *), void *pre_data, char **argv) | |||
79 | pid = clone(helper_child, (void *) sp, CLONE_VM, &data); | 75 | pid = clone(helper_child, (void *) sp, CLONE_VM, &data); |
80 | if (pid < 0) { | 76 | if (pid < 0) { |
81 | ret = -errno; | 77 | ret = -errno; |
82 | printk("run_helper : clone failed, errno = %d\n", errno); | 78 | printk(UM_KERN_ERR "run_helper : clone failed, errno = %d\n", |
79 | errno); | ||
83 | goto out_free2; | 80 | goto out_free2; |
84 | } | 81 | } |
85 | 82 | ||
@@ -96,10 +93,9 @@ int run_helper(void (*pre_exec)(void *), void *pre_data, char **argv) | |||
96 | } else { | 93 | } else { |
97 | if (n < 0) { | 94 | if (n < 0) { |
98 | n = -errno; | 95 | n = -errno; |
99 | printk("run_helper : read on pipe failed, ret = %d\n", | 96 | printk(UM_KERN_ERR "run_helper : read on pipe failed, " |
100 | -n); | 97 | "ret = %d\n", -n); |
101 | ret = n; | 98 | ret = n; |
102 | kill(pid, SIGKILL); | ||
103 | } | 99 | } |
104 | CATCH_EINTR(waitpid(pid, NULL, __WCLONE)); | 100 | CATCH_EINTR(waitpid(pid, NULL, __WCLONE)); |
105 | } | 101 | } |
@@ -129,50 +125,40 @@ int run_helper_thread(int (*proc)(void *), void *arg, unsigned int flags, | |||
129 | pid = clone(proc, (void *) sp, flags, arg); | 125 | pid = clone(proc, (void *) sp, flags, arg); |
130 | if (pid < 0) { | 126 | if (pid < 0) { |
131 | err = -errno; | 127 | err = -errno; |
132 | printk("run_helper_thread : clone failed, errno = %d\n", | 128 | printk(UM_KERN_ERR "run_helper_thread : clone failed, " |
133 | errno); | 129 | "errno = %d\n", errno); |
134 | return err; | 130 | return err; |
135 | } | 131 | } |
136 | if (stack_out == NULL) { | 132 | if (stack_out == NULL) { |
137 | CATCH_EINTR(pid = waitpid(pid, &status, __WCLONE)); | 133 | CATCH_EINTR(pid = waitpid(pid, &status, __WCLONE)); |
138 | if (pid < 0) { | 134 | if (pid < 0) { |
139 | err = -errno; | 135 | err = -errno; |
140 | printk("run_helper_thread - wait failed, errno = %d\n", | 136 | printk(UM_KERN_ERR "run_helper_thread - wait failed, " |
141 | errno); | 137 | "errno = %d\n", errno); |
142 | pid = err; | 138 | pid = err; |
143 | } | 139 | } |
144 | if (!WIFEXITED(status) || (WEXITSTATUS(status) != 0)) | 140 | if (!WIFEXITED(status) || (WEXITSTATUS(status) != 0)) |
145 | printk("run_helper_thread - thread returned status " | 141 | printk(UM_KERN_ERR "run_helper_thread - thread " |
146 | "0x%x\n", status); | 142 | "returned status 0x%x\n", status); |
147 | free_stack(stack, 0); | 143 | free_stack(stack, 0); |
148 | } else | 144 | } else |
149 | *stack_out = stack; | 145 | *stack_out = stack; |
150 | return pid; | 146 | return pid; |
151 | } | 147 | } |
152 | 148 | ||
153 | int helper_wait(int pid, int nohang, char *pname) | 149 | int helper_wait(int pid) |
154 | { | 150 | { |
155 | int ret, status; | 151 | int ret, status; |
156 | int wflags = __WCLONE; | 152 | int wflags = __WCLONE; |
157 | 153 | ||
158 | if (nohang) | ||
159 | wflags |= WNOHANG; | ||
160 | |||
161 | if (!pname) | ||
162 | pname = "helper_wait"; | ||
163 | |||
164 | CATCH_EINTR(ret = waitpid(pid, &status, wflags)); | 154 | CATCH_EINTR(ret = waitpid(pid, &status, wflags)); |
165 | if (ret < 0) { | 155 | if (ret < 0) { |
166 | printk(UM_KERN_ERR "%s : waitpid process %d failed, " | 156 | printk(UM_KERN_ERR "helper_wait : waitpid process %d failed, " |
167 | "errno = %d\n", pname, pid, errno); | 157 | "errno = %d\n", pid, errno); |
168 | return -errno; | 158 | return -errno; |
169 | } else if (nohang && ret == 0) { | ||
170 | printk(UM_KERN_ERR "%s : process %d has not exited\n", | ||
171 | pname, pid); | ||
172 | return -ECHILD; | ||
173 | } else if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) { | 159 | } else if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) { |
174 | printk(UM_KERN_ERR "%s : process %d didn't exit with " | 160 | printk(UM_KERN_ERR "helper_wait : process %d exited with " |
175 | "status 0\n", pname, pid); | 161 | "status 0x%x\n", pid, status); |
176 | return -ECHILD; | 162 | return -ECHILD; |
177 | } else | 163 | } else |
178 | return 0; | 164 | return 0; |