aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoraurel32 <aurel32@c046a42c-6fe2-441c-8c8c-71466251a162>2008-12-18 22:44:04 +0000
committeraurel32 <aurel32@c046a42c-6fe2-441c-8c8c-71466251a162>2008-12-18 22:44:04 +0000
commit2b1319c85c94b7defef2ac2191bb50d773c81db4 (patch)
tree14e178eb62fc1cdd9a41f29e4c85509c5e0b6da9
parent6f9c5ee782e983f00e81a7cbd98900bdac9b3e6c (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.c12
-rw-r--r--gdbstub.h1
-rw-r--r--linux-user/main.c4
-rw-r--r--linux-user/syscall.c22
4 files changed, 26 insertions, 13 deletions
diff --git a/gdbstub.c b/gdbstub.c
index 72feac67bb..2e112b252d 100644
--- a/gdbstub.c
+++ b/gdbstub.c
@@ -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)
{
diff --git a/gdbstub.h b/gdbstub.h
index 1ba7931f77..4bfd872f31 100644
--- a/gdbstub.h
+++ b/gdbstub.h
@@ -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;
}