summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gdb/Makefile.in9
-rw-r--r--gdb/common/common.m42
-rw-r--r--gdb/common/signal-dispositions-save-restore.c65
-rw-r--r--gdb/common/signal-dispositions-save-restore.h40
-rwxr-xr-xgdb/configure2
-rw-r--r--gdb/fork-child.c4
-rw-r--r--gdb/gdbserver/Makefile.in4
-rw-r--r--gdb/gdbserver/config.in3
-rwxr-xr-xgdb/gdbserver/configure2
-rw-r--r--gdb/gdbserver/linux-low.c4
-rw-r--r--gdb/gdbserver/server.c4
-rw-r--r--gdb/main.c2
-rw-r--r--gdb/testsuite/gdb.base/signal-dispositions-child.c62
-rw-r--r--gdb/testsuite/gdb.base/signal-dispositions-child.exp80
-rw-r--r--gdb/testsuite/gdb.gdb/selftest.exp4
15 files changed, 280 insertions, 7 deletions
diff --git a/gdb/Makefile.in b/gdb/Makefile.in
index 5af61036e8e..20549de1de7 100644
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -897,6 +897,7 @@ SFILES = ada-exp.y ada-lang.c ada-typeprint.c ada-valprint.c ada-tasks.c \
target/waitstatus.c common/print-utils.c common/rsp-low.c \
common/errors.c common/common-debug.c common/common-exceptions.c \
common/btrace-common.c common/fileio.c common/common-regcache.c \
+ common/signal-dispositions-save-restore.c \
$(SUBDIR_GCC_COMPILE_SRCS)
LINTFILES = $(SFILES) $(YYFILES) $(CONFIG_SRCS) init.c
@@ -989,7 +990,8 @@ common/common-exceptions.h target/target.h common/symbol.h \
common/common-regcache.h fbsd-tdep.h nat/linux-personality.h \
common/fileio.h nat/x86-linux.h nat/x86-linux-dregs.h nat/amd64-linux-siginfo.h\
nat/linux-namespaces.h arch/arm.h common/gdb_sys_time.h arch/aarch64-insn.h \
-tid-parse.h ser-event.h
+tid-parse.h ser-event.h \
+common/signal-dispositions-save-restore.h
# Header files that already have srcdir in them, or which are in objdir.
@@ -1049,6 +1051,7 @@ COMMON_OBS = $(DEPFILES) $(CONFIG_OBS) $(YYOBJ) \
build-id.o buildsym.o \
findcmd.o \
std-regs.o \
+ signal-dispositions-save-restore.o \
signals.o \
exec.o reverse.o \
bcache.o objfiles.o observer.o minsyms.o maint.o demangle.o \
@@ -2286,6 +2289,10 @@ common-regcache.o: ${srcdir}/common/common-regcache.c
$(COMPILE) $(srcdir)/common/common-regcache.c
$(POSTCOMPILE)
+signal-dispositions-save-restore.o: $(srcdir)/common/signal-dispositions-save-restore.c
+ $(COMPILE) $(srcdir)/common/signal-dispositions-save-restore.c
+ $(POSTCOMPILE)
+
#
# gdb/target/ dependencies
#
diff --git a/gdb/common/common.m4 b/gdb/common/common.m4
index 1342503aaf4..68afc65ba27 100644
--- a/gdb/common/common.m4
+++ b/gdb/common/common.m4
@@ -30,7 +30,7 @@ AC_DEFUN([GDB_AC_COMMON], [
sys/un.h sys/wait.h dnl
thread_db.h wait.h)
- AC_CHECK_FUNCS([fdwalk getrlimit pipe pipe2 socketpair])
+ AC_CHECK_FUNCS([fdwalk getrlimit pipe pipe2 socketpair sigaction])
AC_CHECK_DECLS([strerror, strstr])
diff --git a/gdb/common/signal-dispositions-save-restore.c b/gdb/common/signal-dispositions-save-restore.c
new file mode 100644
index 00000000000..422ebf22b87
--- /dev/null
+++ b/gdb/common/signal-dispositions-save-restore.c
@@ -0,0 +1,65 @@
+/* Copyright (C) 2016 Free Software Foundation, Inc.
+
+ This file is part of GDB.
+
+ 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 "common-defs.h"
+#include "signal-dispositions-save-restore.h"
+
+#include <signal.h>
+
+/* The original signal handlers. */
+
+#ifdef HAVE_SIGACTION
+static sighandler_t original_signal_handlers[NSIG];
+#endif
+
+/* See signal-dispositions-save-restore.h. */
+
+void
+save_original_signal_dispositions (void)
+{
+#ifdef HAVE_SIGACTION
+ int i;
+
+ for (i = 1; i < NSIG; i++)
+ {
+ struct sigaction oldact;
+
+ sigaction (i, NULL, &oldact);
+
+ original_signal_handlers[i] = oldact.sa_handler;
+
+ /* If we find a signal handler already installed, then this
+ function was called too late. */
+ if (oldact.sa_handler != SIG_DFL
+ && oldact.sa_handler != SIG_IGN)
+ internal_error (__FILE__, __LINE__, _("unexpected signal handler"));
+ }
+#endif
+}
+
+/* See signal-dispositions-save-restore.h. */
+
+void
+restore_original_signal_dispositions (void)
+{
+#ifdef HAVE_SIGACTION
+ int i;
+
+ for (i = 1; i < NSIG; i++)
+ signal (i, original_signal_handlers[i]);
+#endif
+}
diff --git a/gdb/common/signal-dispositions-save-restore.h b/gdb/common/signal-dispositions-save-restore.h
new file mode 100644
index 00000000000..71c33655bf0
--- /dev/null
+++ b/gdb/common/signal-dispositions-save-restore.h
@@ -0,0 +1,40 @@
+/* Copyright (C) 2016 Free Software Foundation, Inc.
+
+ This file is part of GDB.
+
+ 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/>. */
+
+#ifndef COMMON_SIGNAL_DISPOSITIONS_SAVE_RESTORE_H
+#define COMMON_SIGNAL_DISPOSITIONS_SAVE_RESTORE_H
+
+/* Save/restore the signal disposition of all signals.
+
+ Since the exec family of functions does not reset the signal
+ disposition of signals set to SIG_IGN, in order to be transparent,
+ when spawning new child processes to debug (with "run", etc.), we
+ must reset all signal dispositions back to what was originally
+ inherited from gdb/gdbserver's parent, just before execing the
+ target program to debug. */
+
+/* Save the signal disposition of all signals, to be restored by
+ restore_original_signal_dispositions. */
+
+extern void save_original_signal_dispositions (void);
+
+/* Restore the signal disposition of all signals, as saved by a call
+ to save_original_signals_disposition. */
+
+extern void restore_original_signal_dispositions (void);
+
+#endif /* COMMON_SIGNAL_DISPOSITIONS_SAVE_RESTORE_H */
diff --git a/gdb/configure b/gdb/configure
index 067f86e5e27..fde6503edf5 100755
--- a/gdb/configure
+++ b/gdb/configure
@@ -12243,7 +12243,7 @@ fi
done
- for ac_func in fdwalk getrlimit pipe pipe2 socketpair
+ for ac_func in fdwalk getrlimit pipe pipe2 socketpair sigaction
do :
as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
diff --git a/gdb/fork-child.c b/gdb/fork-child.c
index 8ac3befd78b..1c1a4bff010 100644
--- a/gdb/fork-child.c
+++ b/gdb/fork-child.c
@@ -32,7 +32,7 @@
#include "solib.h"
#include "filestuff.h"
#include "top.h"
-
+#include "signal-dispositions-save-restore.h"
#include <signal.h>
/* This just gets used as a default if we can't find SHELL. */
@@ -366,6 +366,8 @@ fork_inferior (char *exec_file_arg, char *allargs, char **env,
saying "not parent". Sorry; you'll have to use print
statements! */
+ restore_original_signal_dispositions ();
+
/* There is no execlpe call, so we have to set the environment
for our child in the global variable. If we've vforked, this
clobbers the parent, but environ is restored a few lines down
diff --git a/gdb/gdbserver/Makefile.in b/gdb/gdbserver/Makefile.in
index 2be61eff4af..4e4279a0da2 100644
--- a/gdb/gdbserver/Makefile.in
+++ b/gdb/gdbserver/Makefile.in
@@ -200,6 +200,7 @@ OBS = agent.o ax.o inferiors.o regcache.o remote-utils.o server.o signals.o \
common-utils.o ptid.o buffer.o format.o filestuff.o dll.o notif.o \
tdesc.o print-utils.o rsp-low.o errors.o common-debug.o cleanups.o \
common-exceptions.o symbol.o btrace-common.o fileio.o common-regcache.o \
+ signal-dispositions-save-restore.o \
$(XML_BUILTIN) $(DEPFILES) $(LIBOBJS)
GDBREPLAY_OBS = gdbreplay.o version.o
GDBSERVER_LIBS = @GDBSERVER_LIBS@
@@ -715,6 +716,9 @@ fileio.o: ../common/fileio.c
common-regcache.o: ../common/common-regcache.c
$(COMPILE) $<
$(POSTCOMPILE)
+signal-dispositions-save-restore.o: ../common/signal-dispositions-save-restore.c
+ $(COMPILE) $<
+ $(POSTCOMPILE)
# Arch object files rules form ../arch
diff --git a/gdb/gdbserver/config.in b/gdb/gdbserver/config.in
index 2c3a69a2c61..04072cf56b7 100644
--- a/gdb/gdbserver/config.in
+++ b/gdb/gdbserver/config.in
@@ -202,6 +202,9 @@
/* Define to 1 if you have the <sgtty.h> header file. */
#undef HAVE_SGTTY_H
+/* Define to 1 if you have the `sigaction' function. */
+#undef HAVE_SIGACTION
+
/* Define to 1 if you have the <signal.h> header file. */
#undef HAVE_SIGNAL_H
diff --git a/gdb/gdbserver/configure b/gdb/gdbserver/configure
index 2926deb51f6..0a3436e6aff 100755
--- a/gdb/gdbserver/configure
+++ b/gdb/gdbserver/configure
@@ -5912,7 +5912,7 @@ fi
done
- for ac_func in fdwalk getrlimit pipe pipe2 socketpair
+ for ac_func in fdwalk getrlimit pipe pipe2 socketpair sigaction
do :
as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
diff --git a/gdb/gdbserver/linux-low.c b/gdb/gdbserver/linux-low.c
index 1839f998aff..6bc618993f5 100644
--- a/gdb/gdbserver/linux-low.c
+++ b/gdb/gdbserver/linux-low.c
@@ -22,7 +22,7 @@
#include "agent.h"
#include "tdesc.h"
#include "rsp-low.h"
-
+#include "signal-dispositions-save-restore.h"
#include "nat/linux-nat.h"
#include "nat/linux-waitpid.h"
#include "gdb_wait.h"
@@ -975,6 +975,8 @@ linux_create_inferior (char *program, char **allargs)
}
}
+ restore_original_signal_dispositions ();
+
execv (program, allargs);
if (errno == ENOENT)
execvp (program, allargs);
diff --git a/gdb/gdbserver/server.c b/gdb/gdbserver/server.c
index 6d6cb0923e8..d5209472823 100644
--- a/gdb/gdbserver/server.c
+++ b/gdb/gdbserver/server.c
@@ -22,7 +22,7 @@
#include "notif.h"
#include "tdesc.h"
#include "rsp-low.h"
-
+#include "signal-dispositions-save-restore.h"
#include <ctype.h>
#include <unistd.h>
#if HAVE_SIGNAL_H
@@ -3611,6 +3611,8 @@ captured_main (int argc, char *argv[])
opened by remote_prepare. */
notice_open_fds ();
+ save_original_signal_dispositions ();
+
/* We need to know whether the remote connection is stdio before
starting the inferior. Inferiors created in this scenario have
stdin,stdout redirected. So do this here before we call
diff --git a/gdb/main.c b/gdb/main.c
index 5477379b249..a018d84ef10 100644
--- a/gdb/main.c
+++ b/gdb/main.c
@@ -44,6 +44,7 @@
#include <signal.h>
#include "event-top.h"
#include "infrun.h"
+#include "signal-dispositions-save-restore.h"
/* The selected interpreter. This will be used as a set command
variable, so it should always be malloc'ed - since
@@ -505,6 +506,7 @@ captured_main (void *data)
bfd_init ();
notice_open_fds ();
+ save_original_signal_dispositions ();
make_cleanup (VEC_cleanup (cmdarg_s), &cmdarg_vec);
dirsize = 1;
diff --git a/gdb/testsuite/gdb.base/signal-dispositions-child.c b/gdb/testsuite/gdb.base/signal-dispositions-child.c
new file mode 100644
index 00000000000..2e93d622b25
--- /dev/null
+++ b/gdb/testsuite/gdb.base/signal-dispositions-child.c
@@ -0,0 +1,62 @@
+/* Copyright 2016 Free Software Foundation, Inc.
+
+ This file is part of GDB.
+
+ 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 <stdlib.h>
+#include <stdio.h>
+#include <signal.h>
+
+#ifndef OUTPUT_TXT
+# define OUTPUT_TXT "output.txt"
+#endif
+
+int
+main (int argc, char **argv)
+{
+ int i;
+ FILE *out;
+
+ if (argc > 1)
+ out = stdout;
+ else
+ {
+ out = fopen (OUTPUT_TXT, "w");
+ if (out == NULL)
+ {
+ fprintf (stderr, "File open failed\n");
+ exit (1);
+ }
+ }
+
+ for (i = 1; i < NSIG; i++)
+ {
+ struct sigaction oldact;
+
+ sigaction (i, NULL, &oldact);
+
+ if (oldact.sa_handler == SIG_DFL)
+ fprintf (out, "%d: SIG_DFL\n", i);
+ else if (oldact.sa_handler == SIG_IGN)
+ fprintf (out, "%d: SIG_IGN\n", i);
+ else
+ abort ();
+ }
+
+ if (out != stdout)
+ fclose (out);
+
+ return 0;
+}
diff --git a/gdb/testsuite/gdb.base/signal-dispositions-child.exp b/gdb/testsuite/gdb.base/signal-dispositions-child.exp
new file mode 100644
index 00000000000..4a926b8f265
--- /dev/null
+++ b/gdb/testsuite/gdb.base/signal-dispositions-child.exp
@@ -0,0 +1,80 @@
+# Copyright 2016 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/>.
+
+# Test that gdb's (or gdbserver's) own signal handling does not
+# interfere with the signal dispositions their spawned children
+# inherit.
+#
+# - If gdb inherits some signal set to SIG_IGN, so should the
+# inferior, even if gdb itself chooses not to ignore the signal.
+#
+# - If gdb inherits some signal set to SIG_DFL, so should the inferior
+# even if gdb itself ignores that signal.
+#
+# This requires special support in gdb/gdbserver because the exec
+# family of functions do not reset the signal disposition of signals
+# that are set to SIG_IGN.
+
+standard_testfile
+
+set gdb_txt [standard_output_file gdb.txt]
+set standalone_txt [standard_output_file standalone.txt]
+remote_exec host "rm -f $gdb_txt"
+remote_exec host "rm -f $standalone_txt"
+
+set options [list debug "additional_flags=-DOUTPUT_TXT=\"$gdb_txt\""]
+if {[build_executable $testfile.exp $testfile $srcfile $options]} {
+ untested $testfile.exp
+ return -1
+}
+
+set options [list debug "additional_flags=-DOUTPUT_TXT=\"$standalone_txt\""]
+if {[build_executable $testfile.exp $testfile-standalone $srcfile $options]} {
+ untested $testfile.exp
+ return -1
+}
+
+# Run the program directly, and dump its initial signal dispositions
+# in "standalone.txt".
+
+# Use remote_spawn instead of remote_exec, like how we spawn gdb.
+# This is in order to take the same code code paths in dejagnu
+# compared to when running the program through gdb. E.g., because
+# local_exec uses -ignore SIGHUP, while remote_spawn does not, if we
+# used remote_exec, the test program would start with SIGHUP ignored
+# when run standalone, but not when run through gdb.
+set res [remote_spawn host "$binfile-standalone"]
+if { $res < 0 || $res == "" } {
+ perror "Spawning $binfile-standalone failed."
+ return 1
+}
+remote_close host
+
+# Now run the program through gdb, and dump its initial signal
+# dispositions in "gdb.txt".
+
+clean_restart $binfile
+
+if { ! [ runto_main ] } then {
+ untested $testfile.exp
+ return -1
+}
+
+gdb_continue_to_end
+
+# Diff the .txt files. They should be identical.
+gdb_test "shell diff -s $standalone_txt $gdb_txt" \
+ "Files .* are identical.*" \
+ "diff signal dispositions"
diff --git a/gdb/testsuite/gdb.gdb/selftest.exp b/gdb/testsuite/gdb.gdb/selftest.exp
index 2fdd9e3539f..236f4b79bec 100644
--- a/gdb/testsuite/gdb.gdb/selftest.exp
+++ b/gdb/testsuite/gdb.gdb/selftest.exp
@@ -162,6 +162,10 @@ proc do_steps_and_nexts {} {
set description "next over notice_open_fds"
set command "next"
}
+ -re ".*save_original_signal_dispositions ..;.*$gdb_prompt $" {
+ set description "next over save_original_signal_dispositions"
+ set command "next"
+ }
-re ".*VEC_cleanup .cmdarg_s.*$gdb_prompt $" {
set description "next over cmdarg_s VEC_cleanup"
set command "next"