[Linux] Ask kernel to kill inferior when GDB terminates
authorJoel Brobecker <brobecker@adacore.com>
Tue, 11 Nov 2014 06:07:21 +0000 (10:07 +0400)
committerJoel Brobecker <brobecker@adacore.com>
Tue, 16 Dec 2014 12:56:46 +0000 (07:56 -0500)
This patch enhances GDB on GNU/Linux systems in the situation where
we are debugging an inferior that was created from GDB (as opposed
to attached to), by asking the kernel to kill the inferior if GDB
terminates without doing it itself.

This would typically happen when GDB encounters a problem and
crashes, or when it gets killed by an external process. This can
be observed by starting a program under GDB, and then killing
GDB with signal 9. After GDB is killed, the inferior still remains.

This patch also fixes GDBserver similarly.

This fix is conditional on the kernel supporting the PTRACE_O_EXITKILL
feature.  On older kernels, the behavior remains unchanged.

gdb/ChangeLog:

        * nat/linux-ptrace.h (PTRACE_O_EXITKILL): Define if not
        already defined.
        (linux_enable_event_reporting): Add parameter "attached".
        * nat/linux-ptrace.c (linux_test_for_exitkill): New forward
        declaration.  New function.
        (linux_check_ptrace_features): Add linux_test_for_exitkill call.
        (linux_enable_event_reporting): Add new parameter "attached".
        Do not call ptrace with the PTRACE_O_EXITKILL if ATTACHED is
        nonzero.
        * linux-nat.c (linux_init_ptrace): Add parameter "attached".
        Use it.  Update function description.
        (linux_child_post_attach, linux_child_post_startup_inferior):
        Update call to linux_enable_event_reporting.

gdb/gdbserver/ChangeLog:

        * linux-low.c (linux_low_filter_event): Update call to
        linux_enable_event_reporting following the addition of
        a new parameter to that function.

Tested on x86_64-linux, native and native-gdbserver.

I also verified by hand that the inferior gets killed when killing
GDB in the "run" case, while the inferior remains in the "attach"
case. Same for GDBserver.

gdb/ChangeLog
gdb/gdbserver/ChangeLog
gdb/gdbserver/linux-low.c
gdb/linux-nat.c
gdb/nat/linux-ptrace.c
gdb/nat/linux-ptrace.h

index f3dc30c726e088c3390784a1cc107c03096854b1..2fadb8cf394ff960e75641673924a2b0e5797ff4 100644 (file)
@@ -1,3 +1,19 @@
+2014-12-16  Joel Brobecker  <brobecker@adacore.com>
+
+       * nat/linux-ptrace.h (PTRACE_O_EXITKILL): Define if not
+       already defined.
+       (linux_enable_event_reporting): Add parameter "attached".
+       * nat/linux-ptrace.c (linux_test_for_exitkill): New forward
+       declaration.  New function.
+       (linux_check_ptrace_features): Add linux_test_for_exitkill call.
+       (linux_enable_event_reporting): Add new parameter "attached".
+       Do not call ptrace with the PTRACE_O_EXITKILL if ATTACHED is
+       nonzero.
+       * linux-nat.c (linux_init_ptrace): Add parameter "attached".
+       Use it.  Update function description.
+       (linux_child_post_attach, linux_child_post_startup_inferior):
+       Update call to linux_enable_event_reporting.
+
 2014-12-16  Yao Qi  <yao@codesourcery.com>
 
        * NEWS: Move some entries to "Changes since GDB 7.8" section.
index 3269b3f01412c51856d69e596a2cc7f987ecc09c..a95bce547a935ba052867d5609a60fe0006c2b77 100644 (file)
@@ -1,3 +1,9 @@
+2014-12-16  Joel Brobecker  <brobecker@adacore.com>
+
+       * linux-low.c (linux_low_filter_event): Update call to
+       linux_enable_event_reporting following the addition of
+       a new parameter to that function.
+
 2014-12-16  Catalin Udma  <catalin.udma@freescale.com>
 
        PR server/17457
index 5ea9200133a4e300db9eb4e1556718a769943aee..65f72a2dda916482a59eb87b8bb830c213d43963 100644 (file)
@@ -1878,7 +1878,9 @@ linux_low_filter_event (ptid_t filter_ptid, int lwpid, int wstat)
 
   if (WIFSTOPPED (wstat) && child->must_set_ptrace_flags)
     {
-      linux_enable_event_reporting (lwpid);
+      struct process_info *proc = find_process_pid (pid_of (thread));
+
+      linux_enable_event_reporting (lwpid, proc->attached);
       child->must_set_ptrace_flags = 0;
     }
 
index 29133f9465f8880804e0de3d56418c4bf9ddffc0..845d56649d79d8dea527dc73988c914c5bf9df46 100644 (file)
@@ -321,25 +321,27 @@ pull_pid_from_list (struct simple_pid_list **listp, int pid, int *statusp)
 }
 
 /* Initialize ptrace warnings and check for supported ptrace
-   features given PID.  */
+   features given PID.
+
+   ATTACHED should be nonzero iff we attached to the inferior.  */
 
 static void
-linux_init_ptrace (pid_t pid)
+linux_init_ptrace (pid_t pid, int attached)
 {
-  linux_enable_event_reporting (pid);
+  linux_enable_event_reporting (pid, attached);
   linux_ptrace_init_warnings ();
 }
 
 static void
 linux_child_post_attach (struct target_ops *self, int pid)
 {
-  linux_init_ptrace (pid);
+  linux_init_ptrace (pid, 1);
 }
 
 static void
 linux_child_post_startup_inferior (struct target_ops *self, ptid_t ptid)
 {
-  linux_init_ptrace (ptid_get_pid (ptid));
+  linux_init_ptrace (ptid_get_pid (ptid), 0);
 }
 
 /* Return the number of known LWPs in the tgid given by PID.  */
index 8bc3f1667ac42cc346e145d15eb7b17a878d682a..a0e0c329b3de1ff8515370be5ea1870fc812592c 100644 (file)
@@ -307,6 +307,7 @@ linux_child_function (gdb_byte *child_stack)
 
 static void linux_test_for_tracesysgood (int child_pid);
 static void linux_test_for_tracefork (int child_pid);
+static void linux_test_for_exitkill (int child_pid);
 
 /* Determine ptrace features available on this target.  */
 
@@ -338,6 +339,8 @@ linux_check_ptrace_features (void)
 
   linux_test_for_tracefork (child_pid);
 
+  linux_test_for_exitkill (child_pid);
+
   /* Clean things up and kill any pending children.  */
   do
     {
@@ -449,19 +452,44 @@ linux_test_for_tracefork (int child_pid)
             "(%d, status 0x%x)"), ret, status);
 }
 
-/* Enable reporting of all currently supported ptrace events.  */
+/* Determine if PTRACE_O_EXITKILL can be used.  */
+
+static void
+linux_test_for_exitkill (int child_pid)
+{
+  int ret;
+
+  ret = ptrace (PTRACE_SETOPTIONS, child_pid, (PTRACE_TYPE_ARG3) 0,
+               (PTRACE_TYPE_ARG4) PTRACE_O_EXITKILL);
+
+  if (ret == 0)
+    current_ptrace_options |= PTRACE_O_EXITKILL;
+}
+
+/* Enable reporting of all currently supported ptrace events.
+   ATTACHED should be nonzero if we have attached to the inferior.  */
 
 void
-linux_enable_event_reporting (pid_t pid)
+linux_enable_event_reporting (pid_t pid, int attached)
 {
+  int ptrace_options;
+
   /* Check if we have initialized the ptrace features for this
      target.  If not, do it now.  */
   if (current_ptrace_options == -1)
     linux_check_ptrace_features ();
 
+  ptrace_options = current_ptrace_options;
+  if (attached)
+    {
+      /* When attached to our inferior, we do not want the inferior
+        to die with us if we terminate unexpectedly.  */
+      ptrace_options &= ~PTRACE_O_EXITKILL;
+    }
+
   /* Set the options.  */
   ptrace (PTRACE_SETOPTIONS, pid, (PTRACE_TYPE_ARG3) 0,
-         (PTRACE_TYPE_ARG4) (uintptr_t) current_ptrace_options);
+         (PTRACE_TYPE_ARG4) (uintptr_t) ptrace_options);
 }
 
 /* Disable reporting of all currently supported ptrace events.  */
index 31a77cd95879de1b2d9b26732b2cc756e4bb7d53..588d38afb69dfd8f19fa1a9d30aca76c1388b76b 100644 (file)
@@ -69,6 +69,11 @@ struct buffer;
 
 #endif /* PTRACE_EVENT_FORK */
 
+#ifndef PTRACE_O_EXITKILL
+/* Only defined in Linux Kernel 3.8 or later.  */
+#define PTRACE_O_EXITKILL      0x00100000
+#endif
+
 #if (defined __bfin__ || defined __frv__ || defined __sh__) \
     && !defined PTRACE_GETFDPIC
 #define PTRACE_GETFDPIC                31
@@ -85,7 +90,7 @@ struct buffer;
 
 extern void linux_ptrace_attach_fail_reason (pid_t pid, struct buffer *buffer);
 extern void linux_ptrace_init_warnings (void);
-extern void linux_enable_event_reporting (pid_t pid);
+extern void linux_enable_event_reporting (pid_t pid, int attached);
 extern void linux_disable_event_reporting (pid_t pid);
 extern int linux_supports_tracefork (void);
 extern int linux_supports_traceclone (void);