Commit | Line | Data |
---|---|---|
6a7f1c20 PA |
1 | /* Support for ignoring signals. |
2 | ||
3 | Copyright (C) 2021 Free Software Foundation, Inc. | |
4 | ||
5 | This file is part of GDB. | |
6 | ||
7 | This program is free software; you can redistribute it and/or modify | |
8 | it under the terms of the GNU General Public License as published by | |
9 | the Free Software Foundation; either version 3 of the License, or | |
10 | (at your option) any later version. | |
11 | ||
12 | This program is distributed in the hope that it will be useful, | |
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
15 | GNU General Public License for more details. | |
16 | ||
17 | You should have received a copy of the GNU General Public License | |
18 | along with this program. If not, see <http://www.gnu.org/licenses/>. */ | |
19 | ||
20 | #ifndef SCOPED_IGNORE_SIGNAL_H | |
21 | #define SCOPED_IGNORE_SIGNAL_H | |
22 | ||
23 | #include <signal.h> | |
24 | ||
606a4313 PA |
25 | /* RAII class used to ignore a signal in a scope. If sigprocmask is |
26 | supported, then the signal is only ignored by the calling thread. | |
27 | Otherwise, the signal disposition is set to SIG_IGN, which affects | |
336b30e5 PA |
28 | the whole process. If ConsumePending is true, the destructor |
29 | consumes a pending Sig. SIGPIPE for example is queued on the | |
30 | thread even if blocked at the time the pipe is written to. SIGTTOU | |
31 | OTOH is not raised at all if the thread writing to the terminal has | |
32 | it blocked. Because SIGTTOU is sent to the whole process instead | |
33 | of to a specific thread, consuming a pending SIGTTOU in the | |
34 | destructor could consume a signal raised due to actions done by | |
35 | some other thread. */ | |
36 | ||
37 | template <int Sig, bool ConsumePending> | |
6a7f1c20 PA |
38 | class scoped_ignore_signal |
39 | { | |
40 | public: | |
41 | scoped_ignore_signal () | |
42 | { | |
606a4313 PA |
43 | #ifdef HAVE_SIGPROCMASK |
44 | sigset_t set, old_state; | |
45 | ||
46 | sigemptyset (&set); | |
47 | sigaddset (&set, Sig); | |
48 | sigprocmask (SIG_BLOCK, &set, &old_state); | |
49 | m_was_blocked = sigismember (&old_state, Sig); | |
50 | #else | |
6a7f1c20 | 51 | m_osig = signal (Sig, SIG_IGN); |
606a4313 | 52 | #endif |
6a7f1c20 PA |
53 | } |
54 | ||
55 | ~scoped_ignore_signal () | |
56 | { | |
606a4313 PA |
57 | #ifdef HAVE_SIGPROCMASK |
58 | if (!m_was_blocked) | |
59 | { | |
60 | sigset_t set; | |
61 | const timespec zero_timeout = {}; | |
62 | ||
63 | sigemptyset (&set); | |
64 | sigaddset (&set, Sig); | |
65 | ||
66 | /* If we got a pending Sig signal, consume it before | |
67 | unblocking. */ | |
336b30e5 PA |
68 | if (ConsumePending) |
69 | sigtimedwait (&set, nullptr, &zero_timeout); | |
606a4313 PA |
70 | |
71 | sigprocmask (SIG_UNBLOCK, &set, nullptr); | |
72 | } | |
73 | #else | |
6a7f1c20 | 74 | signal (Sig, m_osig); |
606a4313 | 75 | #endif |
6a7f1c20 PA |
76 | } |
77 | ||
78 | DISABLE_COPY_AND_ASSIGN (scoped_ignore_signal); | |
79 | ||
80 | private: | |
606a4313 PA |
81 | #ifdef HAVE_SIGPROCMASK |
82 | bool m_was_blocked; | |
83 | #else | |
84 | sighandler_t m_osig; | |
85 | #endif | |
6a7f1c20 PA |
86 | }; |
87 | ||
88 | struct scoped_ignore_signal_nop | |
89 | { | |
90 | /* Note, these can't both be "= default", because otherwise the | |
91 | compiler warns that variables of this type are not used. */ | |
92 | scoped_ignore_signal_nop () | |
93 | {} | |
94 | ~scoped_ignore_signal_nop () | |
95 | {} | |
96 | DISABLE_COPY_AND_ASSIGN (scoped_ignore_signal_nop); | |
97 | }; | |
98 | ||
99 | #ifdef SIGPIPE | |
336b30e5 | 100 | using scoped_ignore_sigpipe = scoped_ignore_signal<SIGPIPE, true>; |
6a7f1c20 PA |
101 | #else |
102 | using scoped_ignore_sigpipe = scoped_ignore_signal_nop; | |
103 | #endif | |
104 | ||
105 | #endif /* SCOPED_IGNORE_SIGNAL_H */ |