From 444d61395b63ff0474e8d150497ac709cf6702f6 Mon Sep 17 00:00:00 2001 From: Pedro Alves Date: Thu, 10 May 2007 21:05:15 +0000 Subject: [PATCH] * target.h (target_ops): Change return type of detach to int. Add join. (join_inferior): New. * server.c (main): Don't skip detach support on mingw32. If the inferior doesn't support detaching return error. Call join_inferior instead of using waitpid. * linux-low.c (linux_join): New. (linux_target_op): Add linux_join. * spu-low.c (spu_join): New. (spu_target_ops): Add spu_join. * win32-low.c (win32_detach): Adapt to new interface. Reopen current_process_handle before detaching. Issue a child resume before detaching. (win32_join): New. (win32_target_op): Add win32_join. --- gdb/gdbserver/ChangeLog | 18 +++++++++++++ gdb/gdbserver/linux-low.c | 14 ++++++++++ gdb/gdbserver/server.c | 35 +++++++++++------------- gdb/gdbserver/spu-low.c | 13 +++++++++ gdb/gdbserver/target.h | 12 +++++++-- gdb/gdbserver/win32-low.c | 57 ++++++++++++++++++++++++++++++++++----- 6 files changed, 120 insertions(+), 29 deletions(-) diff --git a/gdb/gdbserver/ChangeLog b/gdb/gdbserver/ChangeLog index f9499544a6..8cf4496924 100644 --- a/gdb/gdbserver/ChangeLog +++ b/gdb/gdbserver/ChangeLog @@ -1,3 +1,21 @@ +2007-05-10 Pedro Alves + + * target.h (target_ops): Change return type of detach to int. + Add join. + (join_inferior): New. + * server.c (main): Don't skip detach support on mingw32. + If the inferior doesn't support detaching return error. + Call join_inferior instead of using waitpid. + * linux-low.c (linux_join): New. + (linux_target_op): Add linux_join. + * spu-low.c (spu_join): New. + (spu_target_ops): Add spu_join. + * win32-low.c (win32_detach): Adapt to new interface. + Reopen current_process_handle before detaching. Issue a child + resume before detaching. + (win32_join): New. + (win32_target_op): Add win32_join. + 2007-05-10 Pedro Alves * win32-low.c (win32-attach): Fix return value. diff --git a/gdb/gdbserver/linux-low.c b/gdb/gdbserver/linux-low.c index ff4f81e60c..2ea54c3543 100644 --- a/gdb/gdbserver/linux-low.c +++ b/gdb/gdbserver/linux-low.c @@ -293,6 +293,19 @@ linux_detach (void) for_each_inferior (&all_threads, linux_detach_one_process); } +static void +linux_join (void) +{ + extern unsigned long signal_pid; + int status, ret; + + do { + ret = waitpid (signal_pid, &status, 0); + if (WIFEXITED (status) || WIFSIGNALED (status)) + break; + } while (ret != -1 || errno != ECHILD); +} + /* Return nonzero if the given thread is still alive. */ static int linux_thread_alive (unsigned long tid) @@ -1656,6 +1669,7 @@ static struct target_ops linux_target_ops = { linux_attach, linux_kill, linux_detach, + linux_join, linux_thread_alive, linux_resume, linux_wait, diff --git a/gdb/gdbserver/server.c b/gdb/gdbserver/server.c index 61a08a175d..ca18a1d6c4 100644 --- a/gdb/gdbserver/server.c +++ b/gdb/gdbserver/server.c @@ -805,32 +805,27 @@ main (int argc, char *argv[]) case 'Q': handle_general_set (own_buf); break; -#ifndef USE_WIN32API - /* Skip "detach" support on mingw32, since we don't have - waitpid. */ case 'D': fprintf (stderr, "Detaching from inferior\n"); - detach_inferior (); - write_ok (own_buf); - putpkt (own_buf); - remote_close (); - - /* If we are attached, then we can exit. Otherwise, we need to - hang around doing nothing, until the child is gone. */ - if (!attached) + if (detach_inferior () != 0) { - int status, ret; - - do { - ret = waitpid (signal_pid, &status, 0); - if (WIFEXITED (status) || WIFSIGNALED (status)) - break; - } while (ret != -1 || errno != ECHILD); + write_enn (own_buf); + putpkt (own_buf); } + else + { + write_ok (own_buf); + putpkt (own_buf); + remote_close (); - exit (0); -#endif + /* If we are attached, then we can exit. Otherwise, we + need to hang around doing nothing, until the child + is gone. */ + if (!attached) + join_inferior (); + exit (0); + } case '!': if (attached == 0) { diff --git a/gdb/gdbserver/spu-low.c b/gdb/gdbserver/spu-low.c index 0d1c81ad92..5dbc811666 100644 --- a/gdb/gdbserver/spu-low.c +++ b/gdb/gdbserver/spu-low.c @@ -320,6 +320,18 @@ spu_detach (void) ptrace (PTRACE_DETACH, current_tid, 0, 0); } +static void +spu_join (void) +{ + int status, ret; + + do { + ret = waitpid (current_tid, &status, 0); + if (WIFEXITED (status) || WIFSIGNALED (status)) + break; + } while (ret != -1 || errno != ECHILD); +} + /* Return nonzero if the given thread is still alive. */ static int spu_thread_alive (unsigned long tid) @@ -567,6 +579,7 @@ static struct target_ops spu_target_ops = { spu_attach, spu_kill, spu_detach, + spu_join, spu_thread_alive, spu_resume, spu_wait, diff --git a/gdb/gdbserver/target.h b/gdb/gdbserver/target.h index 36cc69a975..66511c90b5 100644 --- a/gdb/gdbserver/target.h +++ b/gdb/gdbserver/target.h @@ -69,9 +69,14 @@ struct target_ops void (*kill) (void); - /* Detach from all inferiors. */ + /* Detach from all inferiors. + Return -1 on failure, and 0 on success. */ - void (*detach) (void); + int (*detach) (void); + + /* Wait for inferiors to end. */ + + void (*join) (void); /* Return 1 iff the thread with process ID PID is alive. */ @@ -207,6 +212,9 @@ void set_target_ops (struct target_ops *); #define store_inferior_registers(regno) \ (*the_target->store_registers) (regno) +#define join_inferior() \ + (*the_target->join) () + unsigned char mywait (char *statusp, int connected_wait); int read_inferior_memory (CORE_ADDR memaddr, unsigned char *myaddr, int len); diff --git a/gdb/gdbserver/win32-low.c b/gdb/gdbserver/win32-low.c index 265c91691f..e980db4c85 100644 --- a/gdb/gdbserver/win32-low.c +++ b/gdb/gdbserver/win32-low.c @@ -683,9 +683,11 @@ win32_kill (void) } /* Detach from all inferiors. */ -static void +static int win32_detach (void) { + HANDLE h; + winapi_DebugActiveProcessStop DebugActiveProcessStop = NULL; winapi_DebugSetProcessKillOnExit DebugSetProcessKillOnExit = NULL; #ifdef _WIN32_WCE @@ -696,13 +698,53 @@ win32_detach (void) DebugActiveProcessStop = GETPROCADDRESS (dll, DebugActiveProcessStop); DebugSetProcessKillOnExit = GETPROCADDRESS (dll, DebugSetProcessKillOnExit); - if (DebugSetProcessKillOnExit != NULL) - DebugSetProcessKillOnExit (FALSE); + if (DebugSetProcessKillOnExit == NULL + || DebugActiveProcessStop == NULL) + return -1; - if (DebugActiveProcessStop != NULL) - DebugActiveProcessStop (current_process_id); - else - win32_kill (); + /* We need a new handle, since DebugActiveProcessStop + closes all the ones that came through the events. */ + if ((h = OpenProcess (PROCESS_ALL_ACCESS, + FALSE, + current_process_id)) == NULL) + { + /* The process died. */ + return -1; + } + + { + struct thread_resume resume; + resume.thread = -1; + resume.step = 0; + resume.sig = 0; + resume.leave_stopped = 0; + win32_resume (&resume); + } + + if (!DebugActiveProcessStop (current_process_id)) + { + CloseHandle (h); + return -1; + } + DebugSetProcessKillOnExit (FALSE); + + current_process_handle = h; + return 0; +} + +/* Wait for inferiors to end. */ +static void +win32_join (void) +{ + if (current_process_id == 0 + || current_process_handle == NULL) + return; + + WaitForSingleObject (current_process_handle, INFINITE); + CloseHandle (current_process_handle); + + current_process_handle = NULL; + current_process_id = 0; } /* Return 1 iff the thread with thread ID TID is alive. */ @@ -1160,6 +1202,7 @@ static struct target_ops win32_target_ops = { win32_attach, win32_kill, win32_detach, + win32_join, win32_thread_alive, win32_resume, win32_wait,