diff options
-rw-r--r-- | gdb/Makefile.in | 9 | ||||
-rw-r--r-- | gdb/common/common.m4 | 2 | ||||
-rw-r--r-- | gdb/common/signal-dispositions-save-restore.c | 65 | ||||
-rw-r--r-- | gdb/common/signal-dispositions-save-restore.h | 40 | ||||
-rwxr-xr-x | gdb/configure | 2 | ||||
-rw-r--r-- | gdb/fork-child.c | 4 | ||||
-rw-r--r-- | gdb/gdbserver/Makefile.in | 4 | ||||
-rw-r--r-- | gdb/gdbserver/config.in | 3 | ||||
-rwxr-xr-x | gdb/gdbserver/configure | 2 | ||||
-rw-r--r-- | gdb/gdbserver/linux-low.c | 4 | ||||
-rw-r--r-- | gdb/gdbserver/server.c | 4 | ||||
-rw-r--r-- | gdb/main.c | 2 | ||||
-rw-r--r-- | gdb/testsuite/gdb.base/signal-dispositions-child.c | 62 | ||||
-rw-r--r-- | gdb/testsuite/gdb.base/signal-dispositions-child.exp | 80 | ||||
-rw-r--r-- | gdb/testsuite/gdb.gdb/selftest.exp | 4 |
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" |