From patchwork Tue Nov 26 21:13:07 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Simon Marchi (Code Review)" X-Patchwork-Id: 36247 Received: (qmail 109599 invoked by alias); 26 Nov 2019 21:13:30 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Delivered-To: mailing list gdb-patches@sourceware.org Received: (qmail 109582 invoked by uid 89); 26 Nov 2019 21:13:30 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-21.1 required=5.0 tests=AWL, BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, KAM_ASCII_DIVIDERS, KAM_SHORT autolearn=ham version=3.3.1 spammy=inherited, apples, sk:call_in X-HELO: mx1.osci.io Received: from polly.osci.io (HELO mx1.osci.io) (8.43.85.229) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Tue, 26 Nov 2019 21:13:26 +0000 Received: by mx1.osci.io (Postfix, from userid 994) id 78721202D0; Tue, 26 Nov 2019 16:13:24 -0500 (EST) Received: from gnutoolchain-gerrit.osci.io (gnutoolchain-gerrit.osci.io [8.43.85.239]) by mx1.osci.io (Postfix) with ESMTP id 4513720413; Tue, 26 Nov 2019 16:13:10 -0500 (EST) Received: from localhost (localhost [127.0.0.1]) by gnutoolchain-gerrit.osci.io (Postfix) with ESMTP id 2DFE328174; Tue, 26 Nov 2019 16:13:10 -0500 (EST) X-Gerrit-PatchSet: 5 Date: Tue, 26 Nov 2019 16:13:07 -0500 From: "Sourceware to Gerrit sync (Code Review)" To: Tom Tromey , Pedro Alves , gdb-patches@sourceware.org Auto-Submitted: auto-generated X-Gerrit-MessageType: newpatchset Subject: [pushed] Add RAII class for blocking gdb signals X-Gerrit-Change-Id: If3f37dc57dd859c226e9e4d79458a0514746e8c6 X-Gerrit-Change-Number: 168 X-Gerrit-ChangeURL: X-Gerrit-Commit: 21987b9c060033d367abc50c29f786df4c21b10c In-Reply-To: References: Reply-To: noreply@gnutoolchain-gerrit.osci.io, tromey@sourceware.org, palves@redhat.com, gdb-patches@sourceware.org MIME-Version: 1.0 Content-Disposition: inline User-Agent: Gerrit/3.0.3-79-g83ff7f88f1 Message-Id: <20191126211310.2DFE328174@gnutoolchain-gerrit.osci.io> The original change was created by Tom Tromey. Change URL: https://gnutoolchain-gerrit.osci.io/r/c/binutils-gdb/+/168 ...................................................................... Add RAII class for blocking gdb signals 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 * 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 * 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 --- M gdb/ChangeLog M gdb/Makefile.in M gdb/config.in M gdb/configure M gdb/cp-support.c M gdb/event-top.c M gdb/gdbserver/ChangeLog M gdb/gdbserver/config.in M gdb/gdbserver/configure M gdb/gdbserver/linux-low.c M gdb/gdbserver/remote-utils.c A gdb/gdbsupport/block-signals.h M gdb/gdbsupport/common.m4 A gdb/gdbsupport/gdb-sigmask.h M gdb/gdbsupport/signals-state-save-restore.c M gdb/guile/guile.c M gdb/linux-nat.c 17 files changed, 391 insertions(+), 38 deletions(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index ca92901..9d4fe36 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,5 +1,23 @@ 2019-11-26 Tom Tromey + * 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 + * acinclude.m4: Include ax_pthread.m4. * Makefile.in (PTHREAD_CFLAGS, PTHREAD_LIBS): New variables. (INTERNAL_CFLAGS_BASE): Use PTHREAD_CFLAGS. diff --git a/gdb/Makefile.in b/gdb/Makefile.in index 404f559..8d248ae 100644 --- a/gdb/Makefile.in +++ b/gdb/Makefile.in @@ -1473,6 +1473,7 @@ 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 \ diff --git a/gdb/config.in b/gdb/config.in index f20693b..61e63e2 100644 --- a/gdb/config.in +++ b/gdb/config.in @@ -342,6 +342,9 @@ /* 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 diff --git a/gdb/configure b/gdb/configure index 50164ac..dd936d2 100755 --- a/gdb/configure +++ b/gdb/configure @@ -2520,6 +2520,73 @@ 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 declares $2. + For example, HP-UX 11i declares gettimeofday. */ +#define $2 innocuous_$2 + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $2 (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#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 @@ 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 diff --git a/gdb/cp-support.c b/gdb/cp-support.c index 90a8d2e..f1ddc74 100644 --- a/gdb/cp-support.c +++ b/gdb/cp-support.c @@ -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 @@ 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) diff --git a/gdb/event-top.c b/gdb/event-top.c index 0396dbc..6c6e0ff 100644 --- a/gdb/event-top.c +++ b/gdb/event-top.c @@ -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 @@ sigset_t zero; sigemptyset (&zero); - sigprocmask (SIG_SETMASK, &zero, 0); + gdb_sigmask (SIG_SETMASK, &zero, 0); } #elif HAVE_SIGSETMASK sigsetmask (0); diff --git a/gdb/gdbserver/ChangeLog b/gdb/gdbserver/ChangeLog index eee4b81..00b0a0d 100644 --- a/gdb/gdbserver/ChangeLog +++ b/gdb/gdbserver/ChangeLog @@ -1,5 +1,12 @@ 2019-11-26 Tom Tromey + * 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 + * Makefile.in (PTHREAD_CFLAGS, PTHREAD_LIBS): New variables. (INTERNAL_CFLAGS_BASE): Use PTHREAD_CFLAGS. (GDBSERVER_LIBS): Use PTHREAD_LIBS. diff --git a/gdb/gdbserver/config.in b/gdb/gdbserver/config.in index 4276bce..3027ffa 100644 --- a/gdb/gdbserver/config.in +++ b/gdb/gdbserver/config.in @@ -195,6 +195,9 @@ /* 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 diff --git a/gdb/gdbserver/configure b/gdb/gdbserver/configure index 882c192..8d34a6c 100755 --- a/gdb/gdbserver/configure +++ b/gdb/gdbserver/configure @@ -1972,6 +1972,119 @@ } # 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 declares $2. + For example, HP-UX 11i declares gettimeofday. */ +#define $2 innocuous_$2 + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $2 (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#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 @@ 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 diff --git a/gdb/gdbserver/linux-low.c b/gdb/gdbserver/linux-low.c index f34811c..688a395 100644 --- a/gdb/gdbserver/linux-low.c +++ b/gdb/gdbserver/linux-low.c @@ -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 here. If it got included by gdb_proc_service.h @@ -2689,7 +2690,7 @@ /* 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 @@ { 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 @@ 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 @@ 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 @@ sigemptyset (&mask); sigaddset (&mask, SIGCHLD); - sigprocmask (SIG_BLOCK, &mask, NULL); + gdb_sigmask (SIG_BLOCK, &mask, NULL); if (enable) { @@ -6223,7 +6224,7 @@ { 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_event_pipe[1] = -1; } - sigprocmask (SIG_UNBLOCK, &mask, NULL); + gdb_sigmask (SIG_UNBLOCK, &mask, NULL); } return previous; diff --git a/gdb/gdbserver/remote-utils.c b/gdb/gdbserver/remote-utils.c index d7da4b7..c7f97f3 100644 --- a/gdb/gdbserver/remote-utils.c +++ b/gdb/gdbserver/remote-utils.c @@ -28,6 +28,7 @@ #include "gdbsupport/rsp-low.h" #include "gdbsupport/netstuff.h" #include "gdbsupport/filestuff.h" +#include "gdbsupport/gdb-sigmask.h" #include #if HAVE_SYS_IOCTL_H #include @@ -807,7 +808,7 @@ 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 index 0000000..3f11aba --- /dev/null +++ b/gdb/gdbsupport/block-signals.h @@ -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 . */ + +#ifndef GDBSUPPORT_BLOCK_SIGNALS_H +#define GDBSUPPORT_BLOCK_SIGNALS_H + +#include + +#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 */ diff --git a/gdb/gdbsupport/common.m4 b/gdb/gdbsupport/common.m4 index f813c04..e993b20 100644 --- a/gdb/gdbsupport/common.m4 +++ b/gdb/gdbsupport/common.m4 @@ -54,6 +54,11 @@ [[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 index 0000000..08ad973 --- /dev/null +++ b/gdb/gdbsupport/gdb-sigmask.h @@ -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 . */ + +#ifndef GDBSUPPORT_GDB_SIGMASK_H +#define GDBSUPPORT_GDB_SIGMASK_H + +#include + +#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 */ diff --git a/gdb/gdbsupport/signals-state-save-restore.c b/gdb/gdbsupport/signals-state-save-restore.c index c66d2dd..25a8220 100644 --- a/gdb/gdbsupport/signals-state-save-restore.c +++ b/gdb/gdbsupport/signals-state-save-restore.c @@ -17,6 +17,7 @@ #include "common-defs.h" #include "signals-state-save-restore.h" +#include "gdbsupport/gdb-sigmask.h" #include @@ -25,10 +26,6 @@ #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 @@ 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 @@ 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 diff --git a/gdb/guile/guile.c b/gdb/guile/guile.c index 55929f4..d745c56 100644 --- a/gdb/guile/guile.c +++ b/gdb/guile/guile.c @@ -36,6 +36,7 @@ #include "guile-internal.h" #endif #include +#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 @@ #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 @@ 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 + { + gdb::block_signals blocker; - /* 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); - -#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.] diff --git a/gdb/linux-nat.c b/gdb/linux-nat.c index 2a63ac7..465b2ac 100644 --- a/gdb/linux-nat.c +++ b/gdb/linux-nat.c @@ -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 @@ 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 @@ 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 @@ 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);