aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gdb/ChangeLog17
-rw-r--r--gdb/Makefile.in9
-rw-r--r--gdb/common/common.m42
-rw-r--r--gdb/common/signals-state-save-restore.c94
-rw-r--r--gdb/common/signals-state-save-restore.h39
-rwxr-xr-xgdb/configure2
-rw-r--r--gdb/fork-child.c4
-rw-r--r--gdb/gdbserver/ChangeLog13
-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/ChangeLog7
-rw-r--r--gdb/testsuite/gdb.base/signals-state-child.c101
-rw-r--r--gdb/testsuite/gdb.base/signals-state-child.exp82
-rw-r--r--gdb/testsuite/gdb.gdb/selftest.exp4
18 files changed, 386 insertions, 7 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index dd87420..bfa131f 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,5 +1,22 @@
2016-08-09 Pedro Alves <palves@redhat.com>
+ PR gdb/18653
+ * Makefile.in (SFILES): Add
+ common/signals-state-save-restore.c.
+ (HFILES_NO_SRCDIR): Add common/signals-state-save-restore.h.
+ (COMMON_OBS): Add signals-state-save-restore.o.
+ (signals-state-save-restore.o): New rule.
+ * configure: Regenerate.
+ * fork-child.c: Include "signals-state-save-restore.h".
+ (fork_inferior): Call restore_original_signals_state.
+ * main.c: Include "signals-state-save-restore.h".
+ (captured_main): Call save_original_signals_state.
+ * common/common.m4: Add sigaction to AC_CHECK_FUNCS checks.
+ * common/signals-state-save-restore.c: New file.
+ * common/signals-state-save-restore.h: New file.
+
+2016-08-09 Pedro Alves <palves@redhat.com>
+
* value.c (unpack_value_bitfield): Skip unpacking if the parent
has no contents buffer to begin with.
diff --git a/gdb/Makefile.in b/gdb/Makefile.in
index 5af6103..7b2df86 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/signals-state-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/signals-state-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 \
+ signals-state-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)
+signals-state-save-restore.o: $(srcdir)/common/signals-state-save-restore.c
+ $(COMPILE) $(srcdir)/common/signals-state-save-restore.c
+ $(POSTCOMPILE)
+
#
# gdb/target/ dependencies
#
diff --git a/gdb/common/common.m4 b/gdb/common/common.m4
index 1342503..68afc65 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/signals-state-save-restore.c b/gdb/common/signals-state-save-restore.c
new file mode 100644
index 0000000..1c00cdd
--- /dev/null
+++ b/gdb/common/signals-state-save-restore.c
@@ -0,0 +1,94 @@
+/* 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 "signals-state-save-restore.h"
+
+#include <signal.h>
+
+/* The original signal actions and mask. */
+
+#ifdef HAVE_SIGACTION
+static struct sigaction original_signal_actions[NSIG];
+
+/* Note that we use sigprocmask without worrying about threads because
+ the save/restore functions are called either from main, or after a
+ fork. In both cases, we know the calling process is single
+ threaded. */
+static sigset_t original_signal_mask;
+#endif
+
+/* See signals-state-save-restore.h. */
+
+void
+save_original_signals_state (void)
+{
+#ifdef HAVE_SIGACTION
+ int i;
+ int res;
+
+ res = sigprocmask (0, NULL, &original_signal_mask);
+ if (res == -1)
+ perror_with_name ("sigprocmask");
+
+ for (i = 1; i < NSIG; i++)
+ {
+ struct sigaction *oldact = &original_signal_actions[i];
+
+ res = sigaction (i, NULL, oldact);
+ if (res == -1 && errno == EINVAL)
+ {
+ /* Some signal numbers in the range are invalid. */
+ continue;
+ }
+ else if (res == -1)
+ perror_with_name ("sigaction");
+
+ /* If we find a custom 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 signals-state-save-restore.h. */
+
+void
+restore_original_signals_state (void)
+{
+#ifdef HAVE_SIGACTION
+ int i;
+ int res;
+
+ for (i = 1; i < NSIG; i++)
+ {
+ res = sigaction (i, &original_signal_actions[i], NULL);
+ if (res == -1 && errno == EINVAL)
+ {
+ /* Some signal numbers in the range are invalid. */
+ continue;
+ }
+ else if (res == -1)
+ perror_with_name ("sigaction");
+ }
+
+ res = sigprocmask (SIG_SETMASK, &original_signal_mask, NULL);
+ if (res == -1)
+ perror_with_name ("sigprocmask");
+#endif
+}
diff --git a/gdb/common/signals-state-save-restore.h b/gdb/common/signals-state-save-restore.h
new file mode 100644
index 0000000..bed77fe
--- /dev/null
+++ b/gdb/common/signals-state-save-restore.h
@@ -0,0 +1,39 @@
+/* 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_SIGNALS_STATE_SAVE_RESTORE_H
+#define COMMON_SIGNALS_STATE_SAVE_RESTORE_H
+
+/* Save/restore the signal actions of all signals, and the signal
+ mask.
+
+ Since the exec family of functions does not reset the signal
+ disposition of signals set to SIG_IGN, nor does it reset the signal
+ mask, in order to be transparent, when spawning new child processes
+ to debug (with "run", etc.), we must reset signal actions and mask
+ back to what was originally inherited from gdb/gdbserver's parent,
+ just before execing the target program to debug. */
+
+/* Save the signal state of all signals. */
+
+extern void save_original_signals_state (void);
+
+/* Restore the signal state of all signals. */
+
+extern void restore_original_signals_state (void);
+
+#endif /* COMMON_SIGNALS_STATE_SAVE_RESTORE_H */
diff --git a/gdb/configure b/gdb/configure
index 8f92ed9..7577ba4 100755
--- a/gdb/configure
+++ b/gdb/configure
@@ -12244,7 +12244,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 8ac3bef..6856cf6 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 "signals-state-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_signals_state ();
+
/* 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/ChangeLog b/gdb/gdbserver/ChangeLog
index e88b001..6986714 100644
--- a/gdb/gdbserver/ChangeLog
+++ b/gdb/gdbserver/ChangeLog
@@ -1,3 +1,16 @@
+2016-08-09 Pedro Alves <palves@redhat.com>
+
+ PR gdb/18653
+ * Makefile.in (OBS): Add signals-state-save-restore.o.
+ (signals-state-save-restore.o): New rule.
+ * config.in: Regenerate.
+ * configure: Regenerate.
+ * linux-low.c: Include "signals-state-save-restore.h".
+ (linux_create_inferior): Call
+ restore_original_signals_state.
+ * server.c: Include "dispositions-save-restore.h".
+ (captured_main): Call save_original_signals_state.
+
2016-08-05 Pedro Alves <palves@redhat.com>
* configure: Regenerate.
diff --git a/gdb/gdbserver/Makefile.in b/gdb/gdbserver/Makefile.in
index 2be61ef..bed2b1e 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 \
+ signals-state-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)
+signals-state-save-restore.o: ../common/signals-state-save-restore.c
+ $(COMPILE) $<
+ $(POSTCOMPILE)
# Arch object files rules form ../arch
diff --git a/gdb/gdbserver/config.in b/gdb/gdbserver/config.in
index 2c3a69a..04072cf 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 80fa1f3..889e35b 100755
--- a/gdb/gdbserver/configure
+++ b/gdb/gdbserver/configure
@@ -5913,7 +5913,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 1839f99..45061ac 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 "signals-state-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_signals_state ();
+
execv (program, allargs);
if (errno == ENOENT)
execvp (program, allargs);
diff --git a/gdb/gdbserver/server.c b/gdb/gdbserver/server.c
index 6d6cb09..6fbd61d 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 "signals-state-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_signals_state ();
+
/* 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 5477379..23d4ca0 100644
--- a/gdb/main.c
+++ b/gdb/main.c
@@ -44,6 +44,7 @@
#include <signal.h>
#include "event-top.h"
#include "infrun.h"
+#include "signals-state-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_signals_state ();
make_cleanup (VEC_cleanup (cmdarg_s), &cmdarg_vec);
dirsize = 1;
diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog
index 4b70059..6581556 100644
--- a/gdb/testsuite/ChangeLog
+++ b/gdb/testsuite/ChangeLog
@@ -1,5 +1,12 @@
2016-08-09 Pedro Alves <palves@redhat.com>
+ PR gdb/18653
+ * gdb.base/signals-state-child.c: New file.
+ * gdb.base/signals-state-child.exp: New file.
+ * gdb.gdb/selftest.exp (do_steps_and_nexts): Add new pattern.
+
+2016-08-09 Pedro Alves <palves@redhat.com>
+
* gdb.dwarf2/bitfield-parent-optimized-out.exp: New file.
2016-08-03 Tom Tromey <tom@tromey.com>
diff --git a/gdb/testsuite/gdb.base/signals-state-child.c b/gdb/testsuite/gdb.base/signals-state-child.c
new file mode 100644
index 0000000..e11fa93
--- /dev/null
+++ b/gdb/testsuite/gdb.base/signals-state-child.c
@@ -0,0 +1,101 @@
+/* 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>
+#include <assert.h>
+#include <errno.h>
+
+#ifndef OUTPUT_TXT
+# define OUTPUT_TXT "output.txt"
+#endif
+
+static void
+perror_and_exit (const char *s)
+{
+ perror (s);
+ exit (1);
+}
+
+int
+main (int argc, char **argv)
+{
+ int i;
+ FILE *out;
+ sigset_t sigset;
+ int res;
+
+ res = sigprocmask (0, NULL, &sigset);
+ if (res != 0)
+ perror_and_exit ("sigprocmask");
+
+ if (argc > 1)
+ out = stdout;
+ else
+ {
+ out = fopen (OUTPUT_TXT, "w");
+ if (out == NULL)
+ perror_and_exit ("fopen");
+ }
+
+ for (i = 1; i < NSIG; i++)
+ {
+ struct sigaction oldact;
+
+ fprintf (out, "signal %d: ", i);
+
+ res = sigaction (i, NULL, &oldact);
+ if (res == -1 && errno == EINVAL)
+ {
+ /* Some signal numbers in the range are invalid. E.g.,
+ signals 32 and 33 on GNU/Linux. */
+ fprintf (out, "invalid");
+ }
+ else if (res == -1)
+ {
+ perror_and_exit ("sigaction");
+ }
+ else
+ {
+ int m;
+
+ fprintf (out, "sigaction={sa_handler=", i);
+
+ if (oldact.sa_handler == SIG_DFL)
+ fprintf (out, "SIG_DFL");
+ else if (oldact.sa_handler == SIG_IGN)
+ fprintf (out, "SIG_IGN");
+ else
+ abort ();
+
+ fprintf (out, ", sa_mask=");
+ for (m = 1; m < NSIG; m++)
+ fprintf (out, "%c", sigismember (&oldact.sa_mask, m) ? '1' : '0');
+
+ fprintf (out, ", sa_flags=%d", oldact.sa_flags);
+
+ fprintf (out, "}, masked=%d", sigismember (&sigset, i));
+ }
+ fprintf (out, "\n");
+ }
+
+ if (out != stdout)
+ fclose (out);
+
+ return 0;
+}
diff --git a/gdb/testsuite/gdb.base/signals-state-child.exp b/gdb/testsuite/gdb.base/signals-state-child.exp
new file mode 100644
index 0000000..f5fdcb2
--- /dev/null
+++ b/gdb/testsuite/gdb.base/signals-state-child.exp
@@ -0,0 +1,82 @@
+# 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 actions (dispositions, etc.) and mask
+# 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 does not reset the signal disposition of signals
+# that are set to SIG_IGN, nor signal masks and flags.
+
+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 actions and
+# mask 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 == "" } {
+ untested "spawning $binfile-standalone failed"
+ return 1
+} else {
+ pass "collect standalone signals state"
+}
+remote_close host
+
+# Now run the program through gdb, and dump its initial signal actions
+# and mask in "gdb.txt".
+
+clean_restart $binfile
+
+if { ! [ runto_main ] } then {
+ untested $testfile.exp
+ return -1
+}
+
+gdb_continue_to_end "collect signals state under gdb"
+
+# Diff the .txt files. They should be identical.
+gdb_test "shell diff -s $standalone_txt $gdb_txt" \
+ "Files .* are identical.*" \
+ "signals states are identical"
diff --git a/gdb/testsuite/gdb.gdb/selftest.exp b/gdb/testsuite/gdb.gdb/selftest.exp
index 2fdd9e3..28d5493 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_signals_state ..;.*$gdb_prompt $" {
+ set description "next over save_original_signals_state"
+ set command "next"
+ }
-re ".*VEC_cleanup .cmdarg_s.*$gdb_prompt $" {
set description "next over cmdarg_s VEC_cleanup"
set command "next"