aboutsummaryrefslogtreecommitdiffstats
path: root/arch/um
diff options
context:
space:
mode:
authorStanislaw Gruszka <stf_xl@wp.pl>2007-12-17 19:19:46 -0500
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-12-17 22:28:15 -0500
commit4dbed85a35ed37d9608f4f32e5d69efa775d6223 (patch)
tree67ab558db8ccaf8d706a25e5ce87b78be241cffb /arch/um
parent5867a78f41f84e5388448da62c183255dc22601f (diff)
uml: stop gdb from deleting breakpoints when running UML
Sometimes when UML is debugged gdb miss breakpoints. When process traced by gdb do fork, debugger remove breakpoints from child address space. There is possibility to trace more than one fork, but this not work with UML, I guess (only guess) there is a deadlock - gdb waits for UML and UML waits for gdb. When clone() is called with SIGCHLD and CLONE_VM flags, gdb see this as PTRACE_EVENT_FORK not as PTRACE_EVENT_CLONE and remove breakpoints from child and at the same time from traced process, because either have the same address space. Maybe it is possible to do fix in gdb, but I'm not sure if there is easy way to find out if traced and child processes share memory. So I do fix for UML, it simply do not call clone() with both SIGCHLD and CLONE_VM flags together. Additionally __WALL flag is used for waitpid() to assure not miss clone and normal process events. [ jdike - checkpatch fixes ] Signed-off-by: Stanislaw Gruszka <stf_xl@wp.pl> Signed-off-by: Jeff Dike <jdike@linux.intel.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'arch/um')
-rw-r--r--arch/um/drivers/net_user.c2
-rw-r--r--arch/um/drivers/slip_user.c12
-rw-r--r--arch/um/drivers/slirp_user.c15
-rw-r--r--arch/um/drivers/ubd_user.c3
-rw-r--r--arch/um/include/os.h2
-rw-r--r--arch/um/os-Linux/aio.c4
-rw-r--r--arch/um/os-Linux/drivers/ethertap_user.c10
-rw-r--r--arch/um/os-Linux/drivers/tuntap_user.c2
-rw-r--r--arch/um/os-Linux/helper.c38
-rw-r--r--arch/um/os-Linux/process.c4
-rw-r--r--arch/um/os-Linux/skas/process.c12
-rw-r--r--arch/um/os-Linux/util.c2
12 files changed, 50 insertions, 56 deletions
diff --git a/arch/um/drivers/net_user.c b/arch/um/drivers/net_user.c
index 90d7f2e8ead8..29185cad9fff 100644
--- a/arch/um/drivers/net_user.c
+++ b/arch/um/drivers/net_user.c
@@ -201,7 +201,7 @@ static int change_tramp(char **argv, char *output, int output_len)
201 close(fds[1]); 201 close(fds[1]);
202 202
203 if (pid > 0) 203 if (pid > 0)
204 CATCH_EINTR(err = waitpid(pid, NULL, 0)); 204 helper_wait(pid, 0, "change_tramp");
205 return pid; 205 return pid;
206} 206}
207 207
diff --git a/arch/um/drivers/slip_user.c b/arch/um/drivers/slip_user.c
index 5f06204d6871..b8711e50da80 100644
--- a/arch/um/drivers/slip_user.c
+++ b/arch/um/drivers/slip_user.c
@@ -77,7 +77,7 @@ static int slip_tramp(char **argv, int fd)
77{ 77{
78 struct slip_pre_exec_data pe_data; 78 struct slip_pre_exec_data pe_data;
79 char *output; 79 char *output;
80 int status, pid, fds[2], err, output_len; 80 int pid, fds[2], err, output_len;
81 81
82 err = os_pipe(fds, 1, 0); 82 err = os_pipe(fds, 1, 0);
83 if (err < 0) { 83 if (err < 0) {
@@ -109,15 +109,7 @@ static int slip_tramp(char **argv, int fd)
109 read_output(fds[0], output, output_len); 109 read_output(fds[0], output, output_len);
110 printk("%s", output); 110 printk("%s", output);
111 111
112 CATCH_EINTR(err = waitpid(pid, &status, 0)); 112 err = helper_wait(pid, 0, argv[0]);
113 if (err < 0)
114 err = errno;
115 else if (!WIFEXITED(status) || (WEXITSTATUS(status) != 0)) {
116 printk(UM_KERN_ERR "'%s' didn't exit with status 0\n", argv[0]);
117 err = -EINVAL;
118 }
119 else err = 0;
120
121 close(fds[0]); 113 close(fds[0]);
122 114
123out_free: 115out_free:
diff --git a/arch/um/drivers/slirp_user.c b/arch/um/drivers/slirp_user.c
index 1865089ff41a..89c1be225fda 100644
--- a/arch/um/drivers/slirp_user.c
+++ b/arch/um/drivers/slirp_user.c
@@ -79,7 +79,7 @@ out:
79static void slirp_close(int fd, void *data) 79static void slirp_close(int fd, void *data)
80{ 80{
81 struct slirp_data *pri = data; 81 struct slirp_data *pri = data;
82 int status,err; 82 int err;
83 83
84 close(fd); 84 close(fd);
85 close(pri->slave); 85 close(pri->slave);
@@ -98,18 +98,9 @@ static void slirp_close(int fd, void *data)
98 "(%d)\n", pri->pid, errno); 98 "(%d)\n", pri->pid, errno);
99 } 99 }
100#endif 100#endif
101 101 err = helper_wait(pri->pid, 1, "slirp_close");
102 CATCH_EINTR(err = waitpid(pri->pid, &status, WNOHANG)); 102 if (err < 0)
103 if (err < 0) {
104 printk(UM_KERN_ERR "slirp_close: waitpid returned %d\n", errno);
105 return;
106 }
107
108 if (err == 0) {
109 printk(UM_KERN_ERR "slirp_close: process %d has not exited\n",
110 pri->pid);
111 return; 103 return;
112 }
113 104
114 pri->pid = -1; 105 pri->pid = -1;
115} 106}
diff --git a/arch/um/drivers/ubd_user.c b/arch/um/drivers/ubd_user.c
index 41d254bd38df..48fc7452bc1d 100644
--- a/arch/um/drivers/ubd_user.c
+++ b/arch/um/drivers/ubd_user.c
@@ -49,8 +49,7 @@ int start_io_thread(unsigned long sp, int *fd_out)
49 goto out_close; 49 goto out_close;
50 } 50 }
51 51
52 pid = clone(io_thread, (void *) sp, CLONE_FILES | CLONE_VM | SIGCHLD, 52 pid = clone(io_thread, (void *) sp, CLONE_FILES | CLONE_VM, NULL);
53 NULL);
54 if(pid < 0){ 53 if(pid < 0){
55 err = -errno; 54 err = -errno;
56 printk("start_io_thread - clone failed : errno = %d\n", errno); 55 printk("start_io_thread - clone failed : errno = %d\n", errno);
diff --git a/arch/um/include/os.h b/arch/um/include/os.h
index fbf0a87c6eaa..6f0d1c741bca 100644
--- a/arch/um/include/os.h
+++ b/arch/um/include/os.h
@@ -214,7 +214,7 @@ extern int execvp_noalloc(char *buf, const char *file, char *const argv[]);
214extern int run_helper(void (*pre_exec)(void *), void *pre_data, char **argv); 214extern int run_helper(void (*pre_exec)(void *), void *pre_data, char **argv);
215extern int run_helper_thread(int (*proc)(void *), void *arg, 215extern int run_helper_thread(int (*proc)(void *), void *arg,
216 unsigned int flags, unsigned long *stack_out); 216 unsigned int flags, unsigned long *stack_out);
217extern int helper_wait(int pid); 217extern int helper_wait(int pid, int nohang, char *pname);
218 218
219 219
220/* tls.c */ 220/* tls.c */
diff --git a/arch/um/os-Linux/aio.c b/arch/um/os-Linux/aio.c
index 4158118c4a56..93dc0c80ebaf 100644
--- a/arch/um/os-Linux/aio.c
+++ b/arch/um/os-Linux/aio.c
@@ -218,7 +218,7 @@ static int init_aio_24(void)
218 goto out_close_pipe; 218 goto out_close_pipe;
219 219
220 err = run_helper_thread(not_aio_thread, NULL, 220 err = run_helper_thread(not_aio_thread, NULL,
221 CLONE_FILES | CLONE_VM | SIGCHLD, &aio_stack); 221 CLONE_FILES | CLONE_VM, &aio_stack);
222 if (err < 0) 222 if (err < 0)
223 goto out_close_pipe; 223 goto out_close_pipe;
224 224
@@ -254,7 +254,7 @@ static int init_aio_26(void)
254 } 254 }
255 255
256 err = run_helper_thread(aio_thread, NULL, 256 err = run_helper_thread(aio_thread, NULL,
257 CLONE_FILES | CLONE_VM | SIGCHLD, &aio_stack); 257 CLONE_FILES | CLONE_VM, &aio_stack);
258 if (err < 0) 258 if (err < 0)
259 return err; 259 return err;
260 260
diff --git a/arch/um/os-Linux/drivers/ethertap_user.c b/arch/um/os-Linux/drivers/ethertap_user.c
index 4ff553603449..07ca0cb472ac 100644
--- a/arch/um/os-Linux/drivers/ethertap_user.c
+++ b/arch/um/os-Linux/drivers/ethertap_user.c
@@ -94,7 +94,7 @@ static int etap_tramp(char *dev, char *gate, int control_me,
94 int control_remote, int data_me, int data_remote) 94 int control_remote, int data_me, int data_remote)
95{ 95{
96 struct etap_pre_exec_data pe_data; 96 struct etap_pre_exec_data pe_data;
97 int pid, status, err, n; 97 int pid, err, n;
98 char version_buf[sizeof("nnnnn\0")]; 98 char version_buf[sizeof("nnnnn\0")];
99 char data_fd_buf[sizeof("nnnnnn\0")]; 99 char data_fd_buf[sizeof("nnnnnn\0")];
100 char gate_buf[sizeof("nnn.nnn.nnn.nnn\0")]; 100 char gate_buf[sizeof("nnn.nnn.nnn.nnn\0")];
@@ -131,13 +131,7 @@ static int etap_tramp(char *dev, char *gate, int control_me,
131 } 131 }
132 if (c != 1) { 132 if (c != 1) {
133 printk(UM_KERN_ERR "etap_tramp : uml_net failed\n"); 133 printk(UM_KERN_ERR "etap_tramp : uml_net failed\n");
134 err = -EINVAL; 134 err = helper_wait(pid, 0, "uml_net");
135 CATCH_EINTR(n = waitpid(pid, &status, 0));
136 if (n < 0)
137 err = -errno;
138 else if (!WIFEXITED(status) || (WEXITSTATUS(status) != 1))
139 printk(UM_KERN_ERR "uml_net didn't exit with "
140 "status 1\n");
141 } 135 }
142 return err; 136 return err;
143} 137}
diff --git a/arch/um/os-Linux/drivers/tuntap_user.c b/arch/um/os-Linux/drivers/tuntap_user.c
index 6c55d3c8ead8..1037a3b6386e 100644
--- a/arch/um/os-Linux/drivers/tuntap_user.c
+++ b/arch/um/os-Linux/drivers/tuntap_user.c
@@ -107,7 +107,7 @@ static int tuntap_open_tramp(char *gate, int *fd_out, int me, int remote,
107 "errno = %d\n", errno); 107 "errno = %d\n", errno);
108 return err; 108 return err;
109 } 109 }
110 CATCH_EINTR(waitpid(pid, NULL, 0)); 110 helper_wait(pid, 0, "tuntap_open_tramp");
111 111
112 cmsg = CMSG_FIRSTHDR(&msg); 112 cmsg = CMSG_FIRSTHDR(&msg);
113 if (cmsg == NULL) { 113 if (cmsg == NULL) {
diff --git a/arch/um/os-Linux/helper.c b/arch/um/os-Linux/helper.c
index 7a72dbb61b0d..fba3f0fefeef 100644
--- a/arch/um/os-Linux/helper.c
+++ b/arch/um/os-Linux/helper.c
@@ -76,7 +76,7 @@ int run_helper(void (*pre_exec)(void *), void *pre_data, char **argv)
76 data.fd = fds[1]; 76 data.fd = fds[1];
77 data.buf = __cant_sleep() ? kmalloc(PATH_MAX, UM_GFP_ATOMIC) : 77 data.buf = __cant_sleep() ? kmalloc(PATH_MAX, UM_GFP_ATOMIC) :
78 kmalloc(PATH_MAX, UM_GFP_KERNEL); 78 kmalloc(PATH_MAX, UM_GFP_KERNEL);
79 pid = clone(helper_child, (void *) sp, CLONE_VM | SIGCHLD, &data); 79 pid = clone(helper_child, (void *) sp, CLONE_VM, &data);
80 if (pid < 0) { 80 if (pid < 0) {
81 ret = -errno; 81 ret = -errno;
82 printk("run_helper : clone failed, errno = %d\n", errno); 82 printk("run_helper : clone failed, errno = %d\n", errno);
@@ -101,7 +101,7 @@ int run_helper(void (*pre_exec)(void *), void *pre_data, char **argv)
101 ret = n; 101 ret = n;
102 kill(pid, SIGKILL); 102 kill(pid, SIGKILL);
103 } 103 }
104 CATCH_EINTR(waitpid(pid, NULL, 0)); 104 CATCH_EINTR(waitpid(pid, NULL, __WCLONE));
105 } 105 }
106 106
107out_free2: 107out_free2:
@@ -126,7 +126,7 @@ int run_helper_thread(int (*proc)(void *), void *arg, unsigned int flags,
126 return -ENOMEM; 126 return -ENOMEM;
127 127
128 sp = stack + UM_KERN_PAGE_SIZE - sizeof(void *); 128 sp = stack + UM_KERN_PAGE_SIZE - sizeof(void *);
129 pid = clone(proc, (void *) sp, flags | SIGCHLD, arg); 129 pid = clone(proc, (void *) sp, flags, arg);
130 if (pid < 0) { 130 if (pid < 0) {
131 err = -errno; 131 err = -errno;
132 printk("run_helper_thread : clone failed, errno = %d\n", 132 printk("run_helper_thread : clone failed, errno = %d\n",
@@ -134,7 +134,7 @@ int run_helper_thread(int (*proc)(void *), void *arg, unsigned int flags,
134 return err; 134 return err;
135 } 135 }
136 if (stack_out == NULL) { 136 if (stack_out == NULL) {
137 CATCH_EINTR(pid = waitpid(pid, &status, 0)); 137 CATCH_EINTR(pid = waitpid(pid, &status, __WCLONE));
138 if (pid < 0) { 138 if (pid < 0) {
139 err = -errno; 139 err = -errno;
140 printk("run_helper_thread - wait failed, errno = %d\n", 140 printk("run_helper_thread - wait failed, errno = %d\n",
@@ -150,14 +150,30 @@ int run_helper_thread(int (*proc)(void *), void *arg, unsigned int flags,
150 return pid; 150 return pid;
151} 151}
152 152
153int helper_wait(int pid) 153int helper_wait(int pid, int nohang, char *pname)
154{ 154{
155 int ret; 155 int ret, status;
156 int wflags = __WCLONE;
156 157
157 CATCH_EINTR(ret = waitpid(pid, NULL, WNOHANG)); 158 if (nohang)
159 wflags |= WNOHANG;
160
161 if (!pname)
162 pname = "helper_wait";
163
164 CATCH_EINTR(ret = waitpid(pid, &status, wflags));
158 if (ret < 0) { 165 if (ret < 0) {
159 ret = -errno; 166 printk(UM_KERN_ERR "%s : waitpid process %d failed, "
160 printk("helper_wait : waitpid failed, errno = %d\n", errno); 167 "errno = %d\n", pname, pid, errno);
161 } 168 return -errno;
162 return ret; 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) {
174 printk(UM_KERN_ERR "%s : process %d didn't exit with "
175 "status 0\n", pname, pid);
176 return -ECHILD;
177 } else
178 return 0;
163} 179}
diff --git a/arch/um/os-Linux/process.c b/arch/um/os-Linux/process.c
index 37781db4ceca..bda5c3150d6c 100644
--- a/arch/um/os-Linux/process.c
+++ b/arch/um/os-Linux/process.c
@@ -101,7 +101,7 @@ void os_kill_process(int pid, int reap_child)
101{ 101{
102 kill(pid, SIGKILL); 102 kill(pid, SIGKILL);
103 if (reap_child) 103 if (reap_child)
104 CATCH_EINTR(waitpid(pid, NULL, 0)); 104 CATCH_EINTR(waitpid(pid, NULL, __WALL));
105} 105}
106 106
107/* This is here uniquely to have access to the userspace errno, i.e. the one 107/* This is here uniquely to have access to the userspace errno, i.e. the one
@@ -130,7 +130,7 @@ void os_kill_ptraced_process(int pid, int reap_child)
130 ptrace(PTRACE_KILL, pid); 130 ptrace(PTRACE_KILL, pid);
131 ptrace(PTRACE_CONT, pid); 131 ptrace(PTRACE_CONT, pid);
132 if (reap_child) 132 if (reap_child)
133 CATCH_EINTR(waitpid(pid, NULL, 0)); 133 CATCH_EINTR(waitpid(pid, NULL, __WALL));
134} 134}
135 135
136/* Don't use the glibc version, which caches the result in TLS. It misses some 136/* Don't use the glibc version, which caches the result in TLS. It misses some
diff --git a/arch/um/os-Linux/skas/process.c b/arch/um/os-Linux/skas/process.c
index d77c81d7068a..e8b7a97e83d3 100644
--- a/arch/um/os-Linux/skas/process.c
+++ b/arch/um/os-Linux/skas/process.c
@@ -64,7 +64,7 @@ void wait_stub_done(int pid)
64 int n, status, err; 64 int n, status, err;
65 65
66 while (1) { 66 while (1) {
67 CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED)); 67 CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED | __WALL));
68 if ((n < 0) || !WIFSTOPPED(status)) 68 if ((n < 0) || !WIFSTOPPED(status))
69 goto bad_wait; 69 goto bad_wait;
70 70
@@ -153,7 +153,7 @@ static void handle_trap(int pid, struct uml_pt_regs *regs,
153 panic("handle_trap - continuing to end of syscall " 153 panic("handle_trap - continuing to end of syscall "
154 "failed, errno = %d\n", errno); 154 "failed, errno = %d\n", errno);
155 155
156 CATCH_EINTR(err = waitpid(pid, &status, WUNTRACED)); 156 CATCH_EINTR(err = waitpid(pid, &status, WUNTRACED | __WALL));
157 if ((err < 0) || !WIFSTOPPED(status) || 157 if ((err < 0) || !WIFSTOPPED(status) ||
158 (WSTOPSIG(status) != SIGTRAP + 0x80)) { 158 (WSTOPSIG(status) != SIGTRAP + 0x80)) {
159 err = ptrace_dump_regs(pid); 159 err = ptrace_dump_regs(pid);
@@ -255,16 +255,18 @@ int start_userspace(unsigned long stub_stack)
255 panic("start_userspace : mmap failed, errno = %d", errno); 255 panic("start_userspace : mmap failed, errno = %d", errno);
256 sp = (unsigned long) stack + UM_KERN_PAGE_SIZE - sizeof(void *); 256 sp = (unsigned long) stack + UM_KERN_PAGE_SIZE - sizeof(void *);
257 257
258 flags = CLONE_FILES | SIGCHLD; 258 flags = CLONE_FILES;
259 if (proc_mm) 259 if (proc_mm)
260 flags |= CLONE_VM; 260 flags |= CLONE_VM;
261 else
262 flags |= SIGCHLD;
261 263
262 pid = clone(userspace_tramp, (void *) sp, flags, (void *) stub_stack); 264 pid = clone(userspace_tramp, (void *) sp, flags, (void *) stub_stack);
263 if (pid < 0) 265 if (pid < 0)
264 panic("start_userspace : clone failed, errno = %d", errno); 266 panic("start_userspace : clone failed, errno = %d", errno);
265 267
266 do { 268 do {
267 CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED)); 269 CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED | __WALL));
268 if (n < 0) 270 if (n < 0)
269 panic("start_userspace : wait failed, errno = %d", 271 panic("start_userspace : wait failed, errno = %d",
270 errno); 272 errno);
@@ -314,7 +316,7 @@ void userspace(struct uml_pt_regs *regs)
314 "pid=%d, ptrace operation = %d, errno = %d\n", 316 "pid=%d, ptrace operation = %d, errno = %d\n",
315 pid, op, errno); 317 pid, op, errno);
316 318
317 CATCH_EINTR(err = waitpid(pid, &status, WUNTRACED)); 319 CATCH_EINTR(err = waitpid(pid, &status, WUNTRACED | __WALL));
318 if (err < 0) 320 if (err < 0)
319 panic("userspace - waitpid failed, errno = %d\n", 321 panic("userspace - waitpid failed, errno = %d\n",
320 errno); 322 errno);
diff --git a/arch/um/os-Linux/util.c b/arch/um/os-Linux/util.c
index ef095436a78c..3e058ce9ffb6 100644
--- a/arch/um/os-Linux/util.c
+++ b/arch/um/os-Linux/util.c
@@ -141,7 +141,7 @@ void os_dump_core(void)
141 * nothing reasonable to do if that fails. 141 * nothing reasonable to do if that fails.
142 */ 142 */
143 143
144 while ((pid = waitpid(-1, NULL, WNOHANG)) > 0) 144 while ((pid = waitpid(-1, NULL, WNOHANG | __WALL)) > 0)
145 os_kill_ptraced_process(pid, 0); 145 os_kill_ptraced_process(pid, 0);
146 146
147 abort(); 147 abort();