2012-02-02 Pedro Alves <palves@redhat.com>
authorPedro Alves <palves@redhat.com>
Thu, 2 Feb 2012 18:06:40 +0000 (18:06 +0000)
committerPedro Alves <palves@redhat.com>
Thu, 2 Feb 2012 18:06:40 +0000 (18:06 +0000)
Try SIGKILL first, then PTRACE_KILL.
* linux-low.c (linux_kill_one_lwp): New.
(linux_kill_one_lwp): Rename to ...
(kill_one_lwp_callback): ... this.  Use the new
linux_kill_one_lwp.

gdb/gdbserver/ChangeLog
gdb/gdbserver/linux-low.c

index cdc8448c7c91c1f21a9f99b27e465a98031d3246..690d2a68c3f710552e6553edd24aa99e6fdaacea 100644 (file)
@@ -1,3 +1,11 @@
+2012-02-02  Pedro Alves  <palves@redhat.com>
+
+       Try SIGKILL first, then PTRACE_KILL.
+       * linux-low.c (linux_kill_one_lwp): New.
+       (linux_kill_one_lwp): Rename to ...
+       (kill_one_lwp_callback): ... this.  Use the new
+       linux_kill_one_lwp.
+
 2012-02-02  Pedro Alves  <palves@redhat.com>
 
        * tracepoint.c (cmd_qtminftpilen): Return 0 if there's no current
index 0a8b3de83c42adb63c48f1bcb2b44ff9c2bca37a..ab34d849131713294027d413e8ce5a84169ab3c7 100644 (file)
@@ -801,10 +801,49 @@ last_thread_of_process_p (struct thread_info *thread)
                         second_thread_of_pid_p, &counter) == NULL);
 }
 
-/* Kill the inferior lwp.  */
+/* Kill LWP.  */
+
+static void
+linux_kill_one_lwp (struct lwp_info *lwp)
+{
+  int pid = lwpid_of (lwp);
+
+  /* PTRACE_KILL is unreliable.  After stepping into a signal handler,
+     there is no signal context, and ptrace(PTRACE_KILL) (or
+     ptrace(PTRACE_CONT, SIGKILL), pretty much the same) acts like
+     ptrace(CONT, pid, 0,0) and just resumes the tracee.  A better
+     alternative is to kill with SIGKILL.  We only need one SIGKILL
+     per process, not one for each thread.  But since we still support
+     linuxthreads, and we also support debugging programs using raw
+     clone without CLONE_THREAD, we send one for each thread.  For
+     years, we used PTRACE_KILL only, so we're being a bit paranoid
+     about some old kernels where PTRACE_KILL might work better
+     (dubious if there are any such, but that's why it's paranoia), so
+     we try SIGKILL first, PTRACE_KILL second, and so we're fine
+     everywhere.  */
+
+  errno = 0;
+  kill (pid, SIGKILL);
+  if (debug_threads)
+    fprintf (stderr,
+            "LKL:  kill (SIGKILL) %s, 0, 0 (%s)\n",
+            target_pid_to_str (ptid_of (lwp)),
+            errno ? strerror (errno) : "OK");
+
+  errno = 0;
+  ptrace (PTRACE_KILL, pid, 0, 0);
+  if (debug_threads)
+    fprintf (stderr,
+            "LKL:  PTRACE_KILL %s, 0, 0 (%s)\n",
+            target_pid_to_str (ptid_of (lwp)),
+            errno ? strerror (errno) : "OK");
+}
+
+/* Callback for `find_inferior'.  Kills an lwp of a given process,
+   except the leader.  */
 
 static int
-linux_kill_one_lwp (struct inferior_list_entry *entry, void *args)
+kill_one_lwp_callback (struct inferior_list_entry *entry, void *args)
 {
   struct thread_info *thread = (struct thread_info *) entry;
   struct lwp_info *lwp = get_thread_lwp (thread);
@@ -829,7 +868,7 @@ linux_kill_one_lwp (struct inferior_list_entry *entry, void *args)
 
   do
     {
-      ptrace (PTRACE_KILL, lwpid_of (lwp), 0, 0);
+      linux_kill_one_lwp (lwp);
 
       /* Make sure it died.  The loop is most likely unnecessary.  */
       pid = linux_wait_for_event (lwp->head.id, &wstat, __WALL);
@@ -854,7 +893,7 @@ linux_kill (int pid)
      first, as PTRACE_KILL will not work otherwise.  */
   stop_all_lwps (0, NULL);
 
-  find_inferior (&all_threads, linux_kill_one_lwp, &pid);
+  find_inferior (&all_threads, kill_one_lwp_callback , &pid);
 
   /* See the comment in linux_kill_one_lwp.  We did not kill the first
      thread in the list, so do so now.  */
@@ -874,7 +913,7 @@ linux_kill (int pid)
 
       do
        {
-         ptrace (PTRACE_KILL, lwpid_of (lwp), 0, 0);
+         linux_kill_one_lwp (lwp);
 
          /* Make sure it died.  The loop is most likely unnecessary.  */
          lwpid = linux_wait_for_event (lwp->head.id, &wstat, __WALL);