aboutsummaryrefslogtreecommitdiff
path: root/gdb/gdbserver
diff options
context:
space:
mode:
Diffstat (limited to 'gdb/gdbserver')
-rw-r--r--gdb/gdbserver/ChangeLog18
-rw-r--r--gdb/gdbserver/linux-low.c14
-rw-r--r--gdb/gdbserver/server.c35
-rw-r--r--gdb/gdbserver/spu-low.c13
-rw-r--r--gdb/gdbserver/target.h12
-rw-r--r--gdb/gdbserver/win32-low.c57
6 files changed, 120 insertions, 29 deletions
diff --git a/gdb/gdbserver/ChangeLog b/gdb/gdbserver/ChangeLog
index f949954..8cf4496 100644
--- a/gdb/gdbserver/ChangeLog
+++ b/gdb/gdbserver/ChangeLog
@@ -1,5 +1,23 @@
2007-05-10 Pedro Alves <pedro_alves@portugalmail.pt>
+ * 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 <pedro_alves@portugalmail.pt>
+
* win32-low.c (win32-attach): Fix return value.
* target.h (target_ops): Describe ATTACH return values.
diff --git a/gdb/gdbserver/linux-low.c b/gdb/gdbserver/linux-low.c
index ff4f81e..2ea54c3 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 61a08a1..ca18a1d 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 0d1c81a..5dbc811 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 36cc69a..66511c9 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 265c916..e980db4 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,