This is the mail archive of the gdb-cvs@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[binutils-gdb] [lynxos] gdbserver hangs when killing inferior from GDB


https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=4abd5ed2221c826bcb843794286777452de5c50b

commit 4abd5ed2221c826bcb843794286777452de5c50b
Author: Joel Brobecker <brobecker@adacore.com>
Date:   Sun Dec 20 09:39:40 2015 -0500

    [lynxos] gdbserver hangs when killing inferior from GDB
    
    With any program under GDBserver control on LynxOS, killing
    the program from the debugger (using the "kill" command) causes
    GDBserver to properly kill the inferior but GDBserver then hangs.
    
    This change of behavior occured after the following change was
    applied:
    
        commit f0ea042932e6922c90df3fd0001497d287b97677
        Date:   Mon Nov 30 16:05:27 2015 +0000
        Subject: gdbserver: don't exit until GDB disconnects
    
    One of the changes introduced by the commit above is that
    process_serial_event no longer calls exit after handling
    the vKill packet. Instead, what happens is that we wait
    until captured_main finds that we no longer have any inferior
    to debug, at which point it throws_quit. This (normal) exception
    is then expected to propagate all the way to the exception handle
    in function "main", which calls exit.
    
    However, before the exception gets propagated, the cleanups
    are first executed, and one of the cleanups in question is
    detach_or_kill_for_exit_cleanup, which was put in place by
    captured_main. detach_or_kill_for_exit_cleanup is basically
    a wrapper around detach_or_kill_for_exit, which iterates
    over all inferiors, and kills them all.
    
    In our case, we have only one inferior, which we have already
    killed during the handling for the "vKill" packet. Unfortunately,
    we did not properly clean our internal data for that inferior up,
    and so detach_or_kill_for_exit thinks that we still have one inferior,
    and therefore tries to kill it. This results in lynx_kill being
    called, doing the following:
    
        lynx_ptrace (PTRACE_KILL, ptid, 0, 0, 0);
        lynx_wait (ptid, &status, 0);
        the_target->mourn (process);
    
    The hang is caused by the call to lynx_wait, which waits for
    an event from a process which does not exist...
    
    This patch fixes the issue by enhancing lynx_mourn to clean
    the threads and process list up.
    
    gdb/gdbserver/ChangeLog:
    
            * lynx-low.c (lynx_delete_thread_callback): New function.
            (lynx_mourn): Properly delete our process and all of its
            threads.  Remove call to clear_inferiors.

Diff:
---
 gdb/gdbserver/ChangeLog  |  6 ++++++
 gdb/gdbserver/lynx-low.c | 22 +++++++++++++++++++++-
 2 files changed, 27 insertions(+), 1 deletion(-)

diff --git a/gdb/gdbserver/ChangeLog b/gdb/gdbserver/ChangeLog
index a80a088..dd19262 100644
--- a/gdb/gdbserver/ChangeLog
+++ b/gdb/gdbserver/ChangeLog
@@ -1,5 +1,11 @@
 2015-12-22  Joel Brobecker  <brobecker@adacore.com>
 
+	* lynx-low.c (lynx_delete_thread_callback): New function.
+	(lynx_mourn): Properly delete our process and all of its
+	threads.  Remove call to clear_inferiors.
+
+2015-12-22  Joel Brobecker  <brobecker@adacore.com>
+
 	* target.c (thread_search_callback): Add check that
 	the thread_stopped target callback is not NULL before
 	calling it.
diff --git a/gdb/gdbserver/lynx-low.c b/gdb/gdbserver/lynx-low.c
index 2940ce5..2821ff0 100644
--- a/gdb/gdbserver/lynx-low.c
+++ b/gdb/gdbserver/lynx-low.c
@@ -546,16 +546,36 @@ lynx_detach (int pid)
   return 0;
 }
 
+/* A callback for find_inferior which removes from the thread list
+   all threads belonging to process PROC.  */
+
+static int
+lynx_delete_thread_callback (struct inferior_list_entry *entry, void *proc)
+{
+  struct process_info *process = (struct process_info *) proc;
+
+  if (ptid_get_pid (entry->id) == pid_of (process))
+    {
+      struct thread_info *thr = find_thread_ptid (entry->id);
+
+      remove_thread (thr);
+    }
+
+  return 0;
+}
+
 /* Implement the mourn target_ops method.  */
 
 static void
 lynx_mourn (struct process_info *proc)
 {
+  find_inferior (&all_threads, lynx_delete_thread_callback, proc);
+
   /* Free our private data.  */
   free (proc->priv);
   proc->priv = NULL;
 
-  clear_inferiors ();
+  remove_process (proc);
 }
 
 /* Implement the join target_ops method.  */


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]