Add RAII class for blocking gdb signals
authorTom Tromey <tom@tromey.com>
Sun, 29 Sep 2019 14:50:15 +0000 (08:50 -0600)
committerTom Tromey <tom@tromey.com>
Tue, 26 Nov 2019 21:02:57 +0000 (14:02 -0700)
This adds configury support and an RAII class that can be used to
temporarily block signals that are used by gdb.  (This class is not
used in this patch, but it split out for easier review.)

The idea of this patch is that these signals should only be delivered
to the main thread.  So, when creating a background thread, they are
temporarily blocked; the blocked state is inherited by the new thread.

The sigprocmask man page says:

    The use of sigprocmask() is unspecified in a multithreaded
    process; see pthread_sigmask(3).

This patch changes gdb to use pthread_sigmask when appropriate, by
introducing a convenience define.

I've updated gdbserver as well, because I had to touch gdbsupport, and
because the threading patches will make it link against the thread
library.

I chose not to touch the NTO code, because I don't know anything about
that platform and because I cannot test it.

Finally, this modifies an existing spot in the Guile layer to use the
new facility.

gdb/ChangeLog
2019-11-26  Tom Tromey  <tom@tromey.com>

* gdbsupport/signals-state-save-restore.c (original_signal_mask):
Remove comment.
(save_original_signals_state, restore_original_signals_state): Use
gdb_sigmask.
* linux-nat.c (block_child_signals, restore_child_signals_mask)
(_initialize_linux_nat): Use gdb_sigmask.
* guile/guile.c (_initialize_guile): Use block_signals.
* Makefile.in (HFILES_NO_SRCDIR): Add gdb-sigmask.h.
* gdbsupport/gdb-sigmask.h: New file.
* event-top.c (async_sigtstp_handler): Use gdb_sigmask.
* cp-support.c (gdb_demangle): Use gdb_sigmask.
* gdbsupport/common.m4 (GDB_AC_COMMON): Check for
pthread_sigmask.
* configure, config.in: Rebuild.
* gdbsupport/block-signals.h: New file.

gdb/gdbserver/ChangeLog
2019-11-26  Tom Tromey  <tom@tromey.com>

* remote-utils.c (block_unblock_async_io): Use gdb_sigmask.
* linux-low.c (linux_wait_for_event_filtered, linux_async): Use
gdb_sigmask.
* configure, config.in: Rebuild.

Change-Id: If3f37dc57dd859c226e9e4d79458a0514746e8c6

17 files changed:
gdb/ChangeLog
gdb/Makefile.in
gdb/config.in
gdb/configure
gdb/cp-support.c
gdb/event-top.c
gdb/gdbserver/ChangeLog
gdb/gdbserver/config.in
gdb/gdbserver/configure
gdb/gdbserver/linux-low.c
gdb/gdbserver/remote-utils.c
gdb/gdbsupport/block-signals.h [new file with mode: 0644]
gdb/gdbsupport/common.m4
gdb/gdbsupport/gdb-sigmask.h [new file with mode: 0644]
gdb/gdbsupport/signals-state-save-restore.c
gdb/guile/guile.c
gdb/linux-nat.c

index ca9290180cc5386f84e2eaf6c5c7cdcb30cc26da..9d4fe360b27d16d5a8800fb4d52b465099ece624 100644 (file)
@@ -1,3 +1,21 @@
+2019-11-26  Tom Tromey  <tom@tromey.com>
+
+       * gdbsupport/signals-state-save-restore.c (original_signal_mask):
+       Remove comment.
+       (save_original_signals_state, restore_original_signals_state): Use
+       gdb_sigmask.
+       * linux-nat.c (block_child_signals, restore_child_signals_mask)
+       (_initialize_linux_nat): Use gdb_sigmask.
+       * guile/guile.c (_initialize_guile): Use block_signals.
+       * Makefile.in (HFILES_NO_SRCDIR): Add gdb-sigmask.h.
+       * gdbsupport/gdb-sigmask.h: New file.
+       * event-top.c (async_sigtstp_handler): Use gdb_sigmask.
+       * cp-support.c (gdb_demangle): Use gdb_sigmask.
+       * gdbsupport/common.m4 (GDB_AC_COMMON): Check for
+       pthread_sigmask.
+       * configure, config.in: Rebuild.
+       * gdbsupport/block-signals.h: New file.
+
 2019-11-26  Tom Tromey  <tom@tromey.com>
 
        * acinclude.m4: Include ax_pthread.m4.
index 404f559baef3d3df65f91f5d722b79b56670c0da..8d248ae780268d183252bda16c4b6472491adb8c 100644 (file)
@@ -1473,6 +1473,7 @@ HFILES_NO_SRCDIR = \
        gdbsupport/fileio.h \
        gdbsupport/format.h \
        gdbsupport/gdb-dlfcn.h \
+       gdbsupport/gdb-sigmask.h \
        gdbsupport/gdb_assert.h \
        gdbsupport/gdb_binary_search.h \
        gdbsupport/gdb_tilde_expand.h \
index f20693b05d8d9d4c6e3071e89b10dccc51c7b321..61e63e2330033ef94cfb6a5dea752ca861ec5cbd 100644 (file)
 /* Have PTHREAD_PRIO_INHERIT. */
 #undef HAVE_PTHREAD_PRIO_INHERIT
 
+/* Define to 1 if you have the `pthread_sigmask' function. */
+#undef HAVE_PTHREAD_SIGMASK
+
 /* Define to 1 if you have the `ptrace64' function. */
 #undef HAVE_PTRACE64
 
index 50164ac8a4aedf65d49865f38cbbef6ef7c353c4..dd936d247e395a6a860df17db78efdd4f1aa9ef8 100755 (executable)
@@ -2520,6 +2520,73 @@ fi
   as_fn_set_status $ac_retval
 
 } # ac_fn_cxx_try_link
+
+# ac_fn_cxx_check_func LINENO FUNC VAR
+# ------------------------------------
+# Tests whether FUNC exists, setting the cache variable VAR accordingly
+ac_fn_cxx_check_func ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if eval \${$3+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+/* Define $2 to an innocuous variant, in case <limits.h> declares $2.
+   For example, HP-UX 11i <limits.h> declares gettimeofday.  */
+#define $2 innocuous_$2
+
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char $2 (); below.
+    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+    <limits.h> exists even on freestanding compilers.  */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef $2
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char $2 ();
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined __stub_$2 || defined __stub___$2
+choke me
+#endif
+
+int
+main ()
+{
+return $2 ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_link "$LINENO"; then :
+  eval "$3=yes"
+else
+  eval "$3=no"
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+fi
+eval ac_res=\$$3
+              { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+
+} # ac_fn_cxx_check_func
 cat >config.log <<_ACEOF
 This file contains any messages produced by compilers while
 running configure, to aid debugging if configure makes a mistake.
@@ -14263,6 +14330,21 @@ rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
 fi
 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $gdb_cv_cxx_std_thread" >&5
 $as_echo "$gdb_cv_cxx_std_thread" >&6; }
+
+    # This check must be here, while LIBS includes any necessary
+    # threading library.
+    for ac_func in pthread_sigmask
+do :
+  ac_fn_cxx_check_func "$LINENO" "pthread_sigmask" "ac_cv_func_pthread_sigmask"
+if test "x$ac_cv_func_pthread_sigmask" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_PTHREAD_SIGMASK 1
+_ACEOF
+
+fi
+done
+
+
     LIBS="$save_LIBS"
     CXXFLAGS="$save_CXXFLAGS"
   fi
index 90a8d2ece04f2581dedc995a1a37416458ca75d7..f1ddc74976d12175c1a5809b0246dca5e988ffe4 100644 (file)
@@ -37,6 +37,7 @@
 #include "gdbsupport/gdb_setjmp.h"
 #include "safe-ctype.h"
 #include "gdbsupport/selftest.h"
+#include "gdbsupport/gdb-sigmask.h"
 
 #define d_left(dc) (dc)->u.s_binary.left
 #define d_right(dc) (dc)->u.s_binary.right
@@ -1572,7 +1573,7 @@ gdb_demangle (const char *name, int options)
          sigset_t segv_sig_set;
          sigemptyset (&segv_sig_set);
          sigaddset (&segv_sig_set, SIGSEGV);
-         sigprocmask (SIG_UNBLOCK, &segv_sig_set, NULL);
+         gdb_sigmask (SIG_UNBLOCK, &segv_sig_set, NULL);
 #endif
 
          if (!error_reported)
index 0396dbcc52de74db3fbe32d41e33f04a3451c968..6c6e0ff3baae9f4be672d0308f8cf924d3fc6c81 100644 (file)
@@ -40,6 +40,7 @@
 #include "gdbsupport/buffer.h"
 #include "ser-event.h"
 #include "gdb_select.h"
+#include "gdbsupport/gdb-sigmask.h"
 
 /* readline include files.  */
 #include "readline/readline.h"
@@ -1127,7 +1128,7 @@ async_sigtstp_handler (gdb_client_data arg)
     sigset_t zero;
 
     sigemptyset (&zero);
-    sigprocmask (SIG_SETMASK, &zero, 0);
+    gdb_sigmask (SIG_SETMASK, &zero, 0);
   }
 #elif HAVE_SIGSETMASK
   sigsetmask (0);
index eee4b818a25ad99b471eb3e0ff3373f0ce9bda5b..00b0a0df025690be0f28289f81d0744c196af2a9 100644 (file)
@@ -1,3 +1,10 @@
+2019-11-26  Tom Tromey  <tom@tromey.com>
+
+       * remote-utils.c (block_unblock_async_io): Use gdb_sigmask.
+       * linux-low.c (linux_wait_for_event_filtered, linux_async): Use
+       gdb_sigmask.
+       * configure, config.in: Rebuild.
+
 2019-11-26  Tom Tromey  <tom@tromey.com>
 
        * Makefile.in (PTHREAD_CFLAGS, PTHREAD_LIBS): New variables.
index 4276bce9af06023170dc4f6dd7832112b9636934..3027ffa1b1c1f6c086c5f258060052e05a528746 100644 (file)
 /* Have PTHREAD_PRIO_INHERIT. */
 #undef HAVE_PTHREAD_PRIO_INHERIT
 
+/* Define to 1 if you have the `pthread_sigmask' function. */
+#undef HAVE_PTHREAD_SIGMASK
+
 /* Define if the target supports PTRACE_GETFPXREGS for extended register
    access. */
 #undef HAVE_PTRACE_GETFPXREGS
index 882c1922a1e152005f55fafe98f6381fa29f5eed..8d34a6c30594f4335d7c87420180ee0025caf1dc 100755 (executable)
@@ -1972,6 +1972,119 @@ $as_echo "$ac_res" >&6; }
 
 } # ac_fn_c_check_decl
 
+# ac_fn_cxx_try_link LINENO
+# -------------------------
+# Try to link conftest.$ac_ext, and return whether this succeeded.
+ac_fn_cxx_try_link ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  rm -f conftest.$ac_objext conftest$ac_exeext
+  if { { ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_link") 2>conftest.err
+  ac_status=$?
+  if test -s conftest.err; then
+    grep -v '^ *+' conftest.err >conftest.er1
+    cat conftest.er1 >&5
+    mv -f conftest.er1 conftest.err
+  fi
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; } && {
+        test -z "$ac_cxx_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest$ac_exeext && {
+        test "$cross_compiling" = yes ||
+        test -x conftest$ac_exeext
+       }; then :
+  ac_retval=0
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       ac_retval=1
+fi
+  # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information
+  # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would
+  # interfere with the next link command; also delete a directory that is
+  # left behind by Apple's compiler.  We do this before executing the actions.
+  rm -rf conftest.dSYM conftest_ipa8_conftest.oo
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+  as_fn_set_status $ac_retval
+
+} # ac_fn_cxx_try_link
+
+# ac_fn_cxx_check_func LINENO FUNC VAR
+# ------------------------------------
+# Tests whether FUNC exists, setting the cache variable VAR accordingly
+ac_fn_cxx_check_func ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if eval \${$3+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+/* Define $2 to an innocuous variant, in case <limits.h> declares $2.
+   For example, HP-UX 11i <limits.h> declares gettimeofday.  */
+#define $2 innocuous_$2
+
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char $2 (); below.
+    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+    <limits.h> exists even on freestanding compilers.  */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef $2
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char $2 ();
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined __stub_$2 || defined __stub___$2
+choke me
+#endif
+
+int
+main ()
+{
+return $2 ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_link "$LINENO"; then :
+  eval "$3=yes"
+else
+  eval "$3=no"
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+fi
+eval ac_res=\$$3
+              { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+
+} # ac_fn_cxx_check_func
+
 # ac_fn_c_compute_int LINENO EXPR VAR INCLUDES
 # --------------------------------------------
 # Tries to find the compile-time value of EXPR in a program that includes
@@ -7609,6 +7722,21 @@ rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
 fi
 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $gdb_cv_cxx_std_thread" >&5
 $as_echo "$gdb_cv_cxx_std_thread" >&6; }
+
+    # This check must be here, while LIBS includes any necessary
+    # threading library.
+    for ac_func in pthread_sigmask
+do :
+  ac_fn_cxx_check_func "$LINENO" "pthread_sigmask" "ac_cv_func_pthread_sigmask"
+if test "x$ac_cv_func_pthread_sigmask" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_PTHREAD_SIGMASK 1
+_ACEOF
+
+fi
+done
+
+
     LIBS="$save_LIBS"
     CXXFLAGS="$save_CXXFLAGS"
   fi
index f34811cda2a5981784a24b344e726bee61e31f61..688a3954028ae40a268b4f8bf2879e034989d724 100644 (file)
@@ -50,6 +50,7 @@
 #include "gdbsupport/common-inferior.h"
 #include "nat/fork-inferior.h"
 #include "gdbsupport/environ.h"
+#include "gdbsupport/gdb-sigmask.h"
 #include "gdbsupport/scoped_restore.h"
 #ifndef ELFMAG0
 /* Don't include <linux/elf.h> here.  If it got included by gdb_proc_service.h
@@ -2689,7 +2690,7 @@ linux_wait_for_event_filtered (ptid_t wait_ptid, ptid_t filter_ptid,
   /* Make sure SIGCHLD is blocked until the sigsuspend below.  Block
      all signals while here.  */
   sigfillset (&block_mask);
-  sigprocmask (SIG_BLOCK, &block_mask, &prev_mask);
+  gdb_sigmask (SIG_BLOCK, &block_mask, &prev_mask);
 
   /* Always pull all events out of the kernel.  We'll randomly select
      an event LWP out of all that have events, to prevent
@@ -2775,7 +2776,7 @@ linux_wait_for_event_filtered (ptid_t wait_ptid, ptid_t filter_ptid,
        {
          if (debug_threads)
            debug_printf ("LLW: exit (no unwaited-for LWP)\n");
-         sigprocmask (SIG_SETMASK, &prev_mask, NULL);
+         gdb_sigmask (SIG_SETMASK, &prev_mask, NULL);
          return -1;
        }
 
@@ -2785,7 +2786,7 @@ linux_wait_for_event_filtered (ptid_t wait_ptid, ptid_t filter_ptid,
          if (debug_threads)
            debug_printf ("WNOHANG set, no event found\n");
 
-         sigprocmask (SIG_SETMASK, &prev_mask, NULL);
+         gdb_sigmask (SIG_SETMASK, &prev_mask, NULL);
          return 0;
        }
 
@@ -2794,11 +2795,11 @@ linux_wait_for_event_filtered (ptid_t wait_ptid, ptid_t filter_ptid,
        debug_printf ("sigsuspend'ing\n");
 
       sigsuspend (&prev_mask);
-      sigprocmask (SIG_SETMASK, &prev_mask, NULL);
+      gdb_sigmask (SIG_SETMASK, &prev_mask, NULL);
       goto retry;
     }
 
-  sigprocmask (SIG_SETMASK, &prev_mask, NULL);
+  gdb_sigmask (SIG_SETMASK, &prev_mask, NULL);
 
   current_thread = event_thread;
 
@@ -6215,7 +6216,7 @@ linux_async (int enable)
       sigemptyset (&mask);
       sigaddset (&mask, SIGCHLD);
 
-      sigprocmask (SIG_BLOCK, &mask, NULL);
+      gdb_sigmask (SIG_BLOCK, &mask, NULL);
 
       if (enable)
        {
@@ -6223,7 +6224,7 @@ linux_async (int enable)
            {
              linux_event_pipe[0] = -1;
              linux_event_pipe[1] = -1;
-             sigprocmask (SIG_UNBLOCK, &mask, NULL);
+             gdb_sigmask (SIG_UNBLOCK, &mask, NULL);
 
              warning ("creating event pipe failed.");
              return previous;
@@ -6249,7 +6250,7 @@ linux_async (int enable)
          linux_event_pipe[1] = -1;
        }
 
-      sigprocmask (SIG_UNBLOCK, &mask, NULL);
+      gdb_sigmask (SIG_UNBLOCK, &mask, NULL);
     }
 
   return previous;
index d7da4b7aed21eee67a2274962d8d0f91ea33a2e8..c7f97f3fbef71ed1224de7434894642f30195c4f 100644 (file)
@@ -28,6 +28,7 @@
 #include "gdbsupport/rsp-low.h"
 #include "gdbsupport/netstuff.h"
 #include "gdbsupport/filestuff.h"
+#include "gdbsupport/gdb-sigmask.h"
 #include <ctype.h>
 #if HAVE_SYS_IOCTL_H
 #include <sys/ioctl.h>
@@ -807,7 +808,7 @@ block_unblock_async_io (int block)
 
   sigemptyset (&sigio_set);
   sigaddset (&sigio_set, SIGIO);
-  sigprocmask (block ? SIG_BLOCK : SIG_UNBLOCK, &sigio_set, NULL);
+  gdb_sigmask (block ? SIG_BLOCK : SIG_UNBLOCK, &sigio_set, NULL);
 #endif
 }
 
diff --git a/gdb/gdbsupport/block-signals.h b/gdb/gdbsupport/block-signals.h
new file mode 100644 (file)
index 0000000..3f11aba
--- /dev/null
@@ -0,0 +1,67 @@
+/* Block signals used by gdb
+
+   Copyright (C) 2019 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 GDBSUPPORT_BLOCK_SIGNALS_H
+#define GDBSUPPORT_BLOCK_SIGNALS_H
+
+#include <signal.h>
+
+#include "gdbsupport/gdb-sigmask.h"
+
+namespace gdb
+{
+
+/* This is an RAII class that temporarily blocks the signals needed by
+   gdb.  This can be used before starting a new thread to ensure that
+   this thread starts with the appropriate signals blocked.  */
+class block_signals
+{
+public:
+  block_signals ()
+  {
+#ifdef HAVE_SIGPROCMASK
+    sigset_t mask;
+    sigemptyset (&mask);
+    sigaddset (&mask, SIGINT);
+    sigaddset (&mask, SIGCHLD);
+    sigaddset (&mask, SIGALRM);
+    sigaddset (&mask, SIGWINCH);
+    gdb_sigmask (SIG_BLOCK, &mask, &m_old_mask);
+#endif
+  }
+
+  ~block_signals ()
+  {
+#ifdef HAVE_SIGPROCMASK
+    gdb_sigmask (SIG_SETMASK, &m_old_mask, nullptr);
+#endif
+  }
+
+  DISABLE_COPY_AND_ASSIGN (block_signals);
+
+private:
+
+#ifdef HAVE_SIGPROCMASK
+  sigset_t m_old_mask;
+#endif
+};
+
+}
+
+#endif /* GDBSUPPORT_BLOCK_SIGNALS_H */
index f813c04fd3f5c33a21ca9ce06b22515f5c0bd4ea..e993b20248757846cdbbbbd89740b06dae21f809 100644 (file)
@@ -54,6 +54,11 @@ AC_DEFUN([GDB_AC_COMMON], [
     [[std::thread t(callback);]])],
                                  gdb_cv_cxx_std_thread=yes,
                                  gdb_cv_cxx_std_thread=no)])
+
+    # This check must be here, while LIBS includes any necessary
+    # threading library.
+    AC_CHECK_FUNCS([pthread_sigmask])
+
     LIBS="$save_LIBS"
     CXXFLAGS="$save_CXXFLAGS"
   fi
diff --git a/gdb/gdbsupport/gdb-sigmask.h b/gdb/gdbsupport/gdb-sigmask.h
new file mode 100644 (file)
index 0000000..08ad973
--- /dev/null
@@ -0,0 +1,45 @@
+/* sigprocmask wrapper for gdb
+
+   Copyright (C) 2019 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 GDBSUPPORT_GDB_SIGMASK_H
+#define GDBSUPPORT_GDB_SIGMASK_H
+
+#include <signal.h>
+
+#ifdef HAVE_SIGPROCMASK
+
+#ifdef HAVE_PTHREAD_SIGMASK
+#define gdb_sigmask pthread_sigmask
+#else
+#define gdb_sigmask sigprocmask
+#endif
+
+#else /* HAVE_SIGPROCMASK */
+
+/* Other code checks HAVE_SIGPROCMASK, but if there happened to be a
+   system that only had pthread_sigmask, we could still use it with
+   some extra changes.  */
+#ifdef HAVE_PTHREAD_SIGMASK
+#error pthead_sigmask available without sigprocmask - please report
+#endif
+
+#endif /* HAVE_SIGPROCMASK */
+
+
+#endif /* GDBSUPPORT_GDB_SIGMASK_H */
index c66d2ddc62f6a36fcb5d6d816bd9d428ff8622f5..25a8220976832c0aa9efc33e8214783c3d20c37b 100644 (file)
@@ -17,6 +17,7 @@
 
 #include "common-defs.h"
 #include "signals-state-save-restore.h"
+#include "gdbsupport/gdb-sigmask.h"
 
 #include <signal.h>
 
 #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
 
@@ -41,7 +38,7 @@ save_original_signals_state (bool quiet)
   int i;
   int res;
 
-  res = sigprocmask (0,  NULL, &original_signal_mask);
+  res = gdb_sigmask (0,  NULL, &original_signal_mask);
   if (res == -1)
     perror_with_name (("sigprocmask"));
 
@@ -110,7 +107,7 @@ restore_original_signals_state (void)
        perror_with_name (("sigaction"));
     }
 
-  res = sigprocmask (SIG_SETMASK,  &original_signal_mask, NULL);
+  res = gdb_sigmask (SIG_SETMASK,  &original_signal_mask, NULL);
   if (res == -1)
     perror_with_name (("sigprocmask"));
 #endif
index 55929f4455177ba443d03fe50fdf7a4d7f7a643d..d745c56ec68aa07e041193aa449b9589bd1787a8 100644 (file)
@@ -36,6 +36,7 @@
 #include "guile-internal.h"
 #endif
 #include <signal.h>
+#include "gdbsupport/block-signals.h"
 
 /* The Guile version we're using.
    We *could* use the macros in libguile/version.h but that would preclude
@@ -798,10 +799,6 @@ _initialize_guile (void)
 
 #if HAVE_GUILE
   {
-#ifdef HAVE_SIGPROCMASK
-    sigset_t sigchld_mask, prev_mask;
-#endif
-
     /* The Python support puts the C side in module "_gdb", leaving the Python
        side to define module "gdb" which imports "_gdb".  There is evidently no
        similar convention in Guile so we skip this.  */
@@ -813,25 +810,20 @@ _initialize_guile (void)
     scm_set_automatic_finalization_enabled (0);
 #endif
 
-#ifdef HAVE_SIGPROCMASK
-    /* Before we initialize Guile, block SIGCHLD.
+    /* Before we initialize Guile, block signals needed by gdb
+       (especially SIGCHLD).
        This is done so that all threads created during Guile initialization
        have SIGCHLD blocked.  PR 17247.
        Really libgc and Guile should do this, but we need to work with
        libgc 7.4.x.  */
-    sigemptyset (&sigchld_mask);
-    sigaddset (&sigchld_mask, SIGCHLD);
-    sigprocmask (SIG_BLOCK, &sigchld_mask, &prev_mask);
-#endif
-
-    /* scm_with_guile is the most portable way to initialize Guile.
-       Plus we need to initialize the Guile support while in Guile mode
-       (e.g., called from within a call to scm_with_guile).  */
-    scm_with_guile (call_initialize_gdb_module, NULL);
+    {
+      gdb::block_signals blocker;
 
-#ifdef HAVE_SIGPROCMASK
-    sigprocmask (SIG_SETMASK, &prev_mask, NULL);
-#endif
+      /* scm_with_guile is the most portable way to initialize Guile.
+        Plus we need to initialize the Guile support while in Guile mode
+        (e.g., called from within a call to scm_with_guile).  */
+      scm_with_guile (call_initialize_gdb_module, NULL);
+    }
 
     /* Set Guile's backtrace to match the "set guile print-stack" default.
        [N.B. The two settings are still separate.]
index 2a63ac727d3fe7ef5568709b2305c36067bfab0d..465b2acd946c9ff463c43c0783f23baa365e3c46 100644 (file)
@@ -67,6 +67,7 @@
 #include "nat/linux-namespaces.h"
 #include "gdbsupport/fileio.h"
 #include "gdbsupport/scope-exit.h"
+#include "gdbsupport/gdb-sigmask.h"
 
 /* This comment documents high-level logic of this file.
 
@@ -764,7 +765,7 @@ block_child_signals (sigset_t *prev_mask)
   if (!sigismember (&blocked_mask, SIGCHLD))
     sigaddset (&blocked_mask, SIGCHLD);
 
-  sigprocmask (SIG_BLOCK, &blocked_mask, prev_mask);
+  gdb_sigmask (SIG_BLOCK, &blocked_mask, prev_mask);
 }
 
 /* Restore child signals mask, previously returned by
@@ -773,7 +774,7 @@ block_child_signals (sigset_t *prev_mask)
 static void
 restore_child_signals_mask (sigset_t *prev_mask)
 {
-  sigprocmask (SIG_SETMASK, prev_mask, NULL);
+  gdb_sigmask (SIG_SETMASK, prev_mask, NULL);
 }
 
 /* Mask of signals to pass directly to the inferior.  */
@@ -4564,7 +4565,7 @@ Enables printf debugging output."),
   sigaction (SIGCHLD, &sigchld_action, NULL);
 
   /* Make sure we don't block SIGCHLD during a sigsuspend.  */
-  sigprocmask (SIG_SETMASK, NULL, &suspend_mask);
+  gdb_sigmask (SIG_SETMASK, NULL, &suspend_mask);
   sigdelset (&suspend_mask, SIGCHLD);
 
   sigemptyset (&blocked_mask);