This is the mail archive of the gdb-patches@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]

[patch] [linux-nat] Fix occasional hang on quit


Hi,

in some cases it may happen you do:

(gdb) quit
A debugging session is active.

  Inferior 1 [process 32336] will be killed.

Quit anyway? (y or n) y
<hang>

And due to blocked signals one cannot even terminate GDB from keyboard.
I remember it myself but I never investigated it more (and SIGKILLed it).

Oleg Nesterov has provided a reproducer, providing a GDB fix.
SIGKILL vs. PTRACE_KILL reviewed by Roland McGrath.
	http://sourceware.org/ml/archer/2011-q1/msg00103.html

Why isn't there only SIGKILL is a question.  I guess it may not work on some
kernels, not sure.  Even on RHEL-4 (linux-2.6.9, no utrace) one could use just
SIGKILL.

With unpatched linux-nat.c it gives:
	FAIL: gdb.base/kill-after-signal.exp: kill (timeout)

This testcase works with gdbserver but it gives false PASS for it.
gdbserver (and thus even gdb client) looks happy due to WNOHANG but in fact it
does not kill it, the debuggee remains running:
	write(2, "Killing all inferiors\n", 22) = 22
	ptrace(PTRACE_KILL, 1654, 0, 0)         = 0
	rt_sigprocmask(SIG_BLOCK, ~[RTMIN RT_1], [], 8) = 0
	wait4(1654, 0x7ffffe0eeaa8, WNOHANG, NULL) = 0
	wait4(1654, 0x7ffffe0eeaa8, WNOHANG|__WCLONE, NULL) = -1 ECHILD (No child processes)
	rt_sigsuspend([]

No regressions on {x86_64,x86_64-m32,i686}-fedora15-linux-gnu.

A comment is welcome although as there is kept the PTRACE_KILL for backward
compatibility I will even check it in in some time.


Thanks,
Jan


gdb/
2011-02-23  Jan Kratochvil  <jan.kratochvil@redhat.com>

	* linux-nat.c (kill_callback): Use SIGKILL first.

gdb/testsuite/
2011-02-23  Jan Kratochvil  <jan.kratochvil@redhat.com>

	* gdb.base/kill-after-signal.c: New file.
	* gdb.base/kill-after-signal.exp: New file.

--- a/gdb/linux-nat.c
+++ b/gdb/linux-nat.c
@@ -3802,6 +3802,18 @@ linux_nat_wait (struct target_ops *ops,
 static int
 kill_callback (struct lwp_info *lp, void *data)
 {
+  /* PTRACE_KILL may resume the inferior.  Send SIGKILL first.  */
+
+  errno = 0;
+  kill (GET_LWP (lp->ptid), SIGKILL);
+  if (debug_linux_nat)
+    fprintf_unfiltered (gdb_stdlog,
+			"KC:  kill (SIGKILL) %s, 0, 0 (%s)\n",
+			target_pid_to_str (lp->ptid),
+			errno ? safe_strerror (errno) : "OK");
+
+  /* Some kernels ignore even SIGKILL for processes under ptrace.  */
+
   errno = 0;
   ptrace (PTRACE_KILL, GET_LWP (lp->ptid), 0, 0);
   if (debug_linux_nat)
--- /dev/null
+++ b/gdb/testsuite/gdb.base/kill-after-signal.c
@@ -0,0 +1,37 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2011 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include <signal.h>
+#include <assert.h>
+#include <unistd.h>
+#include <stdio.h>
+
+void
+handler (int signo)
+{
+  sleep (600);
+  assert (0);
+}
+
+int
+main (void)
+{
+  signal (SIGUSR1, handler);
+  raise (SIGUSR1);
+  assert (0);
+  return 0;
+}
--- /dev/null
+++ b/gdb/testsuite/gdb.base/kill-after-signal.exp
@@ -0,0 +1,29 @@
+# Copyright (C) 2011 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+set testfile "kill-after-signal"
+if [prepare_for_testing ${testfile}.exp ${testfile}] {
+    return -1
+}
+
+gdb_test "handle SIGUSR1 stop print pass" "SIGUSR1\[ \t\]+Yes\[ \t\]+Yes\[ \t\]+Yes\[ \t\]+.*"
+
+if ![runto_main] {
+    return -1
+}
+
+gdb_test "continue" "Program received signal SIGUSR1, .*"
+gdb_test "stepi" "\r\nhandler .*"
+gdb_test "kill" "^y" "kill" "Kill the program being debugged\\? \\(y or n\\) $" "y"


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