aboutsummaryrefslogtreecommitdiffstats
path: root/arch/um/os-Linux/helper.c
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/os-Linux/helper.c
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/os-Linux/helper.c')
-rw-r--r--arch/um/os-Linux/helper.c38
1 files changed, 27 insertions, 11 deletions
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}