Commit 2b1319c85c94b7defef2ac2191bb50d773c81db4
1 parent
6f9c5ee7
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
Showing
4 changed files
with
26 additions
and
13 deletions
gdbstub.c
@@ -1996,6 +1996,18 @@ int gdbserver_start(int port) | @@ -1996,6 +1996,18 @@ int gdbserver_start(int port) | ||
1996 | gdb_accept(); | 1996 | gdb_accept(); |
1997 | return 0; | 1997 | return 0; |
1998 | } | 1998 | } |
1999 | + | ||
2000 | +/* Disable gdb stub for child processes. */ | ||
2001 | +void gdbserver_fork(CPUState *env) | ||
2002 | +{ | ||
2003 | + GDBState *s = gdbserver_state; | ||
2004 | + if (s->fd < 0) | ||
2005 | + return; | ||
2006 | + close(s->fd); | ||
2007 | + s->fd = -1; | ||
2008 | + cpu_breakpoint_remove_all(env, BP_GDB); | ||
2009 | + cpu_watchpoint_remove_all(env, BP_GDB); | ||
2010 | +} | ||
1999 | #else | 2011 | #else |
2000 | static int gdb_chr_can_receive(void *opaque) | 2012 | static int gdb_chr_can_receive(void *opaque) |
2001 | { | 2013 | { |
gdbstub.h
@@ -13,6 +13,7 @@ void gdb_set_stop_cpu(CPUState *env); | @@ -13,6 +13,7 @@ void gdb_set_stop_cpu(CPUState *env); | ||
13 | int gdb_handlesig (CPUState *, int); | 13 | int gdb_handlesig (CPUState *, int); |
14 | void gdb_exit(CPUState *, int); | 14 | void gdb_exit(CPUState *, int); |
15 | int gdbserver_start(int); | 15 | int gdbserver_start(int); |
16 | +void gdbserver_fork(CPUState *); | ||
16 | #else | 17 | #else |
17 | int gdbserver_start(const char *port); | 18 | int gdbserver_start(const char *port); |
18 | #endif | 19 | #endif |
linux-user/main.c
@@ -162,6 +162,7 @@ void fork_end(int child) | @@ -162,6 +162,7 @@ void fork_end(int child) | ||
162 | pthread_cond_init(&exclusive_cond, NULL); | 162 | pthread_cond_init(&exclusive_cond, NULL); |
163 | pthread_cond_init(&exclusive_resume, NULL); | 163 | pthread_cond_init(&exclusive_resume, NULL); |
164 | pthread_mutex_init(&tb_lock, NULL); | 164 | pthread_mutex_init(&tb_lock, NULL); |
165 | + gdbserver_fork(thread_env); | ||
165 | } else { | 166 | } else { |
166 | pthread_mutex_unlock(&exclusive_lock); | 167 | pthread_mutex_unlock(&exclusive_lock); |
167 | pthread_mutex_unlock(&tb_lock); | 168 | pthread_mutex_unlock(&tb_lock); |
@@ -254,6 +255,9 @@ void fork_start(void) | @@ -254,6 +255,9 @@ void fork_start(void) | ||
254 | 255 | ||
255 | void fork_end(int child) | 256 | void fork_end(int child) |
256 | { | 257 | { |
258 | + if (child) { | ||
259 | + gdbserver_fork(thread_env); | ||
260 | + } | ||
257 | } | 261 | } |
258 | #endif | 262 | #endif |
259 | 263 |
linux-user/syscall.c
@@ -2960,17 +2960,17 @@ static int do_fork(CPUState *env, unsigned int flags, abi_ulong newsp, | @@ -2960,17 +2960,17 @@ static int do_fork(CPUState *env, unsigned int flags, abi_ulong newsp, | ||
2960 | return -EINVAL; | 2960 | return -EINVAL; |
2961 | fork_start(); | 2961 | fork_start(); |
2962 | ret = fork(); | 2962 | ret = fork(); |
2963 | -#if defined(USE_NPTL) | ||
2964 | - /* There is a race condition here. The parent process could | ||
2965 | - theoretically read the TID in the child process before the child | ||
2966 | - tid is set. This would require using either ptrace | ||
2967 | - (not implemented) or having *_tidptr to point at a shared memory | ||
2968 | - mapping. We can't repeat the spinlock hack used above because | ||
2969 | - the child process gets its own copy of the lock. */ | ||
2970 | if (ret == 0) { | 2963 | if (ret == 0) { |
2964 | + /* Child Process. */ | ||
2971 | cpu_clone_regs(env, newsp); | 2965 | cpu_clone_regs(env, newsp); |
2972 | fork_end(1); | 2966 | fork_end(1); |
2973 | - /* Child Process. */ | 2967 | +#if defined(USE_NPTL) |
2968 | + /* There is a race condition here. The parent process could | ||
2969 | + theoretically read the TID in the child process before the child | ||
2970 | + tid is set. This would require using either ptrace | ||
2971 | + (not implemented) or having *_tidptr to point at a shared memory | ||
2972 | + mapping. We can't repeat the spinlock hack used above because | ||
2973 | + the child process gets its own copy of the lock. */ | ||
2974 | if (flags & CLONE_CHILD_SETTID) | 2974 | if (flags & CLONE_CHILD_SETTID) |
2975 | put_user_u32(gettid(), child_tidptr); | 2975 | put_user_u32(gettid(), child_tidptr); |
2976 | if (flags & CLONE_PARENT_SETTID) | 2976 | if (flags & CLONE_PARENT_SETTID) |
@@ -2979,14 +2979,10 @@ static int do_fork(CPUState *env, unsigned int flags, abi_ulong newsp, | @@ -2979,14 +2979,10 @@ static int do_fork(CPUState *env, unsigned int flags, abi_ulong newsp, | ||
2979 | if (flags & CLONE_SETTLS) | 2979 | if (flags & CLONE_SETTLS) |
2980 | cpu_set_tls (env, newtls); | 2980 | cpu_set_tls (env, newtls); |
2981 | /* TODO: Implement CLONE_CHILD_CLEARTID. */ | 2981 | /* TODO: Implement CLONE_CHILD_CLEARTID. */ |
2982 | +#endif | ||
2982 | } else { | 2983 | } else { |
2983 | fork_end(0); | 2984 | fork_end(0); |
2984 | } | 2985 | } |
2985 | -#else | ||
2986 | - if (ret == 0) { | ||
2987 | - cpu_clone_regs(env, newsp); | ||
2988 | - } | ||
2989 | -#endif | ||
2990 | } | 2986 | } |
2991 | return ret; | 2987 | return ret; |
2992 | } | 2988 | } |