Skip to content

Commit 336b30e

Browse files
committed
Don't call sigtimedwait for scoped_ignore_sigttou
Because SIGTTOU is sent to the whole process instead of to a specific thread, consuming a pending SIGTTOU in the destructor of scoped_ignore_sigttou could consume a SIGTTOU signal raised due to actions done by some other thread. Simply avoid sigtimedwait in scoped_ignore_sigttou, thus plugging the race. This works because we know that when the thread writes to the terminal and the signal is blocked, the kernel does not raise the signal at all. Tested on GNU/Linux, Solaris 11 and FreeBSD. gdb/ChangeLog: yyyy-mm-dd Pedro Alves <[email protected]> * scoped_ignore_signal.h (scoped_ignore_signal): Add ConsumePending template parameter. (scoped_ignore_signal::~scoped_ignore_signal): Skip calling sigtimedwait if ConsumePending is false. (scoped_ignore_sigpipe): Initialize with ConsumePending=true. * scoped_ignore_sigttou.h (scoped_ignore_sigttou) <m_ignore_signal>: Initialize with ConsumePending=false. Change-Id: I92f754dbc45c45819dce2ce68b8c067d8d5c61b1
1 parent e013d20 commit 336b30e

File tree

3 files changed

+24
-6
lines changed

3 files changed

+24
-6
lines changed

gdb/ChangeLog

+10
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,13 @@
1+
2021-06-17 Pedro Alves <[email protected]>
2+
3+
* scoped_ignore_signal.h (scoped_ignore_signal): Add
4+
ConsumePending template parameter.
5+
(scoped_ignore_signal::~scoped_ignore_signal): Skip calling
6+
sigtimedwait if ConsumePending is false.
7+
(scoped_ignore_sigpipe): Initialize with ConsumePending=true.
8+
* scoped_ignore_sigttou.h (scoped_ignore_sigttou)
9+
<m_ignore_signal>: Initialize with ConsumePending=false.
10+
111
2021-06-17 Pedro Alves <[email protected]>
212

313
* Makefile.in (SELFTESTS_SRCS): Add

gdbsupport/scoped_ignore_signal.h

+13-5
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,16 @@
2525
/* RAII class used to ignore a signal in a scope. If sigprocmask is
2626
supported, then the signal is only ignored by the calling thread.
2727
Otherwise, the signal disposition is set to SIG_IGN, which affects
28-
the whole process. */
29-
30-
template <int Sig>
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>
3138
class scoped_ignore_signal
3239
{
3340
public:
@@ -58,7 +65,8 @@ class scoped_ignore_signal
5865

5966
/* If we got a pending Sig signal, consume it before
6067
unblocking. */
61-
sigtimedwait (&set, nullptr, &zero_timeout);
68+
if (ConsumePending)
69+
sigtimedwait (&set, nullptr, &zero_timeout);
6270

6371
sigprocmask (SIG_UNBLOCK, &set, nullptr);
6472
}
@@ -89,7 +97,7 @@ struct scoped_ignore_signal_nop
8997
};
9098

9199
#ifdef SIGPIPE
92-
using scoped_ignore_sigpipe = scoped_ignore_signal<SIGPIPE>;
100+
using scoped_ignore_sigpipe = scoped_ignore_signal<SIGPIPE, true>;
93101
#else
94102
using scoped_ignore_sigpipe = scoped_ignore_signal_nop;
95103
#endif

gdbsupport/scoped_ignore_sigttou.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ class scoped_ignore_sigttou
7575
DISABLE_COPY_AND_ASSIGN (scoped_ignore_sigttou);
7676

7777
private:
78-
lazy_init<scoped_ignore_signal<SIGTTOU>> m_ignore_signal;
78+
lazy_init<scoped_ignore_signal<SIGTTOU, false>> m_ignore_signal;
7979
};
8080

8181
#else

0 commit comments

Comments
 (0)