diff options
Diffstat (limited to 'gdbsupport')
-rw-r--r-- | gdbsupport/ChangeLog | 9 | ||||
-rw-r--r-- | gdbsupport/scoped_ignore_signal.h | 37 |
2 files changed, 44 insertions, 2 deletions
diff --git a/gdbsupport/ChangeLog b/gdbsupport/ChangeLog index ac424f3..d054899 100644 --- a/gdbsupport/ChangeLog +++ b/gdbsupport/ChangeLog @@ -1,5 +1,14 @@ 2021-06-17 Pedro Alves <pedro@palves.net> + * scoped_ignore_signal.h + (scoped_ignore_signal::scoped_ignore_signal) + [HAVE_SIGPROCMASK]: Use sigprocmask to block the signal instead of + changing the signal disposition for the whole process. + (scoped_ignore_signal::~scoped_ignore_signal) [HAVE_SIGPROCMASK]: + Use sigtimedwait and sigprocmask to flush and unblock the signal. + +2021-06-17 Pedro Alves <pedro@palves.net> + * scoped_ignore_sigttou.h: New file, moved from gdb/ and renamed. 2021-05-17 Andrew Burgess <andrew.burgess@embecosm.com> diff --git a/gdbsupport/scoped_ignore_signal.h b/gdbsupport/scoped_ignore_signal.h index cccd390..55a921c 100644 --- a/gdbsupport/scoped_ignore_signal.h +++ b/gdbsupport/scoped_ignore_signal.h @@ -22,7 +22,10 @@ #include <signal.h> -/* RAII class used to ignore a signal in a scope. */ +/* RAII class used to ignore a signal in a scope. If sigprocmask is + supported, then the signal is only ignored by the calling thread. + Otherwise, the signal disposition is set to SIG_IGN, which affects + the whole process. */ template <int Sig> class scoped_ignore_signal @@ -30,18 +33,48 @@ class scoped_ignore_signal public: scoped_ignore_signal () { +#ifdef HAVE_SIGPROCMASK + sigset_t set, old_state; + + sigemptyset (&set); + sigaddset (&set, Sig); + sigprocmask (SIG_BLOCK, &set, &old_state); + m_was_blocked = sigismember (&old_state, Sig); +#else m_osig = signal (Sig, SIG_IGN); +#endif } ~scoped_ignore_signal () { +#ifdef HAVE_SIGPROCMASK + if (!m_was_blocked) + { + sigset_t set; + const timespec zero_timeout = {}; + + sigemptyset (&set); + sigaddset (&set, Sig); + + /* If we got a pending Sig signal, consume it before + unblocking. */ + sigtimedwait (&set, nullptr, &zero_timeout); + + sigprocmask (SIG_UNBLOCK, &set, nullptr); + } +#else signal (Sig, m_osig); +#endif } DISABLE_COPY_AND_ASSIGN (scoped_ignore_signal); private: - sighandler_t m_osig = nullptr; +#ifdef HAVE_SIGPROCMASK + bool m_was_blocked; +#else + sighandler_t m_osig; +#endif }; struct scoped_ignore_signal_nop |