[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Qemu-devel] [1/2] User-mode GDB stub improvements - handle fork
From: |
Aurelien Jarno |
Subject: |
Re: [Qemu-devel] [1/2] User-mode GDB stub improvements - handle fork |
Date: |
Thu, 18 Dec 2008 23:55:54 +0100 |
User-agent: |
Mutt/1.5.18 (2008-05-17) |
On Fri, Dec 12, 2008 at 02:07:56PM -0500, Daniel Jacobowitz wrote:
> From: Daniel Jacobowitz <address@hidden>
>
> 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 <address@hidden>
Thanks, applied.
> ---
>
> This patch lets GDB debug a parent process, even if it calls fork.
> Otherwise you end up with two QEMU processes sharing a single fd
> for the GDB socket, and both writing replies to it. This will more or
> less stutter along for a while, with GDB discarding lots of errors,
> but eventually the two processes will diverge and things will blow up
> depending on which response GDB sees first.
>
> Index: linux-user/syscall.c
> ===================================================================
> --- linux-user/syscall.c (revision 5995)
> +++ linux-user/syscall.c (working copy)
> @@ -2958,17 +2958,17 @@ static int do_fork(CPUState *env, unsign
> 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)
> @@ -2977,14 +2977,10 @@ static int do_fork(CPUState *env, unsign
> 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;
> }
> Index: linux-user/main.c
> ===================================================================
> --- linux-user/main.c (revision 5995)
> +++ linux-user/main.c (working copy)
> @@ -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
>
> Index: gdbstub.c
> ===================================================================
> --- gdbstub.c (revision 5995)
> +++ gdbstub.c (working copy)
> @@ -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)
> {
> Index: gdbstub.h
> ===================================================================
> --- gdbstub.h (revision 5995)
> +++ gdbstub.h (working copy)
> @@ -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
>
> --
> Daniel Jacobowitz
> CodeSourcery
>
>
>
--
.''`. Aurelien Jarno | GPG: 1024D/F1BCDB73
: :' : Debian developer | Electrical Engineer
`. `' address@hidden | address@hidden
`- people.debian.org/~aurel32 | www.aurel32.net