diff options
author | aurel32 <aurel32@c046a42c-6fe2-441c-8c8c-71466251a162> | 2008-12-18 22:44:04 +0000 |
---|---|---|
committer | aurel32 <aurel32@c046a42c-6fe2-441c-8c8c-71466251a162> | 2008-12-18 22:44:04 +0000 |
commit | 2b1319c85c94b7defef2ac2191bb50d773c81db4 (patch) | |
tree | 14e178eb62fc1cdd9a41f29e4c85509c5e0b6da9 | |
parent | 6f9c5ee782e983f00e81a7cbd98900bdac9b3e6c (diff) |
User-mode GDB stub improvements - handle fork
Close gdbserver in child processes, so that only one stub tries to talk
to GDB at a time. Updated from an earlier patch by Paul Brook.
Signed-off-by: Daniel Jacobowitz <dan@codesourcery.com>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@6095 c046a42c-6fe2-441c-8c8c-71466251a162
-rw-r--r-- | gdbstub.c | 12 | ||||
-rw-r--r-- | gdbstub.h | 1 | ||||
-rw-r--r-- | linux-user/main.c | 4 | ||||
-rw-r--r-- | linux-user/syscall.c | 22 |
4 files changed, 26 insertions, 13 deletions
@@ -1996,6 +1996,18 @@ int gdbserver_start(int port) gdb_accept(); return 0; } + +/* Disable gdb stub for child processes. */ +void gdbserver_fork(CPUState *env) +{ + GDBState *s = gdbserver_state; + if (s->fd < 0) + return; + close(s->fd); + s->fd = -1; + cpu_breakpoint_remove_all(env, BP_GDB); + cpu_watchpoint_remove_all(env, BP_GDB); +} #else static int gdb_chr_can_receive(void *opaque) { @@ -13,6 +13,7 @@ void gdb_set_stop_cpu(CPUState *env); int gdb_handlesig (CPUState *, int); void gdb_exit(CPUState *, int); int gdbserver_start(int); +void gdbserver_fork(CPUState *); #else int gdbserver_start(const char *port); #endif diff --git a/linux-user/main.c b/linux-user/main.c index 52322d4a7f..238165f454 100644 --- a/linux-user/main.c +++ b/linux-user/main.c @@ -162,6 +162,7 @@ void fork_end(int child) pthread_cond_init(&exclusive_cond, NULL); pthread_cond_init(&exclusive_resume, NULL); pthread_mutex_init(&tb_lock, NULL); + gdbserver_fork(thread_env); } else { pthread_mutex_unlock(&exclusive_lock); pthread_mutex_unlock(&tb_lock); @@ -254,6 +255,9 @@ void fork_start(void) void fork_end(int child) { + if (child) { + gdbserver_fork(thread_env); + } } #endif diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 73427abb3b..bd60494bcf 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -2960,17 +2960,17 @@ static int do_fork(CPUState *env, unsigned int flags, abi_ulong newsp, return -EINVAL; fork_start(); ret = fork(); -#if defined(USE_NPTL) - /* There is a race condition here. The parent process could - theoretically read the TID in the child process before the child - tid is set. This would require using either ptrace - (not implemented) or having *_tidptr to point at a shared memory - mapping. We can't repeat the spinlock hack used above because - the child process gets its own copy of the lock. */ if (ret == 0) { + /* Child Process. */ cpu_clone_regs(env, newsp); fork_end(1); - /* Child Process. */ +#if defined(USE_NPTL) + /* There is a race condition here. The parent process could + theoretically read the TID in the child process before the child + tid is set. This would require using either ptrace + (not implemented) or having *_tidptr to point at a shared memory + mapping. We can't repeat the spinlock hack used above because + the child process gets its own copy of the lock. */ if (flags & CLONE_CHILD_SETTID) put_user_u32(gettid(), child_tidptr); if (flags & CLONE_PARENT_SETTID) @@ -2979,14 +2979,10 @@ static int do_fork(CPUState *env, unsigned int flags, abi_ulong newsp, if (flags & CLONE_SETTLS) cpu_set_tls (env, newtls); /* TODO: Implement CLONE_CHILD_CLEARTID. */ +#endif } else { fork_end(0); } -#else - if (ret == 0) { - cpu_clone_regs(env, newsp); - } -#endif } return ret; } |