17
17
#include < cerrno>
18
18
#include < csignal>
19
19
#include < ctime>
20
+ #include < fcntl.h>
20
21
#include < vector>
21
22
22
23
// Multiplexing is implemented using kqueue on systems that support it (BSD
23
- // variants including OSX). On linux we use ppoll, while android uses pselect
24
- // (ppoll is present but not implemented properly). On windows we use WSApoll
25
- // (which does not support signals).
24
+ // variants including OSX). On linux we use ppoll.
26
25
27
26
#if HAVE_SYS_EVENT_H
28
27
#include < sys/event.h>
29
- #elif defined(__ANDROID__)
30
- #include < sys/syscall.h>
31
28
#else
32
29
#include < poll.h>
33
30
#endif
34
31
35
32
using namespace lldb ;
36
33
using namespace lldb_private ;
37
34
38
- static sig_atomic_t g_signal_flags[NSIG];
35
+ namespace {
36
+ struct GlobalSignalInfo {
37
+ sig_atomic_t pipe_fd = -1 ;
38
+ static_assert (sizeof (sig_atomic_t ) >= sizeof (int ),
39
+ " Type too small for a file descriptor" );
40
+ sig_atomic_t flag = 0 ;
41
+ };
42
+ } // namespace
43
+ static GlobalSignalInfo g_signal_info[NSIG];
39
44
40
45
static void SignalHandler (int signo, siginfo_t *info, void *) {
41
46
assert (signo < NSIG);
42
- g_signal_flags[signo] = 1 ;
47
+
48
+ // Set the flag before writing to the pipe!
49
+ g_signal_info[signo].flag = 1 ;
50
+
51
+ int fd = g_signal_info[signo].pipe_fd ;
52
+ if (fd < 0 ) {
53
+ // This can happen with the following (unlikely) sequence of events:
54
+ // 1. Thread 1 gets a signal, starts running the signal handler
55
+ // 2. Thread 2 unregisters the signal handler, setting pipe_fd to -1
56
+ // 3. Signal handler on thread 1 reads -1 out of pipe_fd
57
+ // In this case, we can just ignore the signal because we're no longer
58
+ // interested in it.
59
+ return ;
60
+ }
61
+
62
+ // Write a(ny) character to the pipe to wake up from the poll syscall.
63
+ char c = ' .' ;
64
+ ssize_t bytes_written = llvm::sys::RetryAfterSignal (-1 , ::write , fd, &c, 1 );
65
+ // We can safely ignore EAGAIN (pipe full), as that means poll will definitely
66
+ // return.
67
+ assert (bytes_written == 1 || (bytes_written == -1 && errno == EAGAIN));
43
68
}
44
69
45
70
class MainLoopPosix ::RunImpl {
@@ -48,7 +73,7 @@ class MainLoopPosix::RunImpl {
48
73
~RunImpl () = default ;
49
74
50
75
Status Poll ();
51
- void ProcessEvents ();
76
+ void ProcessReadEvents ();
52
77
53
78
private:
54
79
MainLoopPosix &loop;
@@ -58,15 +83,9 @@ class MainLoopPosix::RunImpl {
58
83
struct kevent out_events[4 ];
59
84
int num_events = -1 ;
60
85
61
- #else
62
- #ifdef __ANDROID__
63
- fd_set read_fd_set;
64
86
#else
65
87
std::vector<struct pollfd > read_fds;
66
88
#endif
67
-
68
- sigset_t get_sigmask ();
69
- #endif
70
89
};
71
90
72
91
#if HAVE_SYS_EVENT_H
@@ -94,7 +113,7 @@ Status MainLoopPosix::RunImpl::Poll() {
94
113
return Status ();
95
114
}
96
115
97
- void MainLoopPosix::RunImpl::ProcessEvents () {
116
+ void MainLoopPosix::RunImpl::ProcessReadEvents () {
98
117
assert (num_events >= 0 );
99
118
for (int i = 0 ; i < num_events; ++i) {
100
119
if (loop.m_terminate_request )
@@ -103,74 +122,19 @@ void MainLoopPosix::RunImpl::ProcessEvents() {
103
122
case EVFILT_READ:
104
123
loop.ProcessReadObject (out_events[i].ident );
105
124
break ;
106
- case EVFILT_SIGNAL:
107
- loop.ProcessSignal (out_events[i].ident );
108
- break ;
109
125
default :
110
126
llvm_unreachable (" Unknown event" );
111
127
}
112
128
}
113
129
}
114
130
#else
115
131
MainLoopPosix::RunImpl::RunImpl (MainLoopPosix &loop) : loop(loop) {
116
- #ifndef __ANDROID__
117
132
read_fds.reserve (loop.m_read_fds .size ());
118
- #endif
119
133
}
120
134
121
- sigset_t MainLoopPosix::RunImpl::get_sigmask () {
122
- sigset_t sigmask;
123
- int ret = pthread_sigmask (SIG_SETMASK, nullptr , &sigmask);
124
- assert (ret == 0 );
125
- UNUSED_IF_ASSERT_DISABLED (ret);
126
-
127
- for (const auto &sig : loop.m_signals )
128
- sigdelset (&sigmask, sig.first );
129
- return sigmask;
130
- }
131
-
132
- #ifdef __ANDROID__
133
- Status MainLoopPosix::RunImpl::Poll () {
134
- // ppoll(2) is not supported on older all android versions. Also, older
135
- // versions android (API <= 19) implemented pselect in a non-atomic way, as a
136
- // combination of pthread_sigmask and select. This is not sufficient for us,
137
- // as we rely on the atomicity to correctly implement signal polling, so we
138
- // call the underlying syscall ourselves.
139
-
140
- FD_ZERO (&read_fd_set);
141
- int nfds = 0 ;
142
- for (const auto &fd : loop.m_read_fds ) {
143
- FD_SET (fd.first , &read_fd_set);
144
- nfds = std::max (nfds, fd.first + 1 );
145
- }
146
-
147
- union {
148
- sigset_t set;
149
- uint64_t pad;
150
- } kernel_sigset;
151
- memset (&kernel_sigset, 0 , sizeof (kernel_sigset));
152
- kernel_sigset.set = get_sigmask ();
153
-
154
- struct {
155
- void *sigset_ptr;
156
- size_t sigset_len;
157
- } extra_data = {&kernel_sigset, sizeof (kernel_sigset)};
158
- if (syscall (__NR_pselect6, nfds, &read_fd_set, nullptr , nullptr , nullptr ,
159
- &extra_data) == -1 ) {
160
- if (errno != EINTR)
161
- return Status (errno, eErrorTypePOSIX);
162
- else
163
- FD_ZERO (&read_fd_set);
164
- }
165
-
166
- return Status ();
167
- }
168
- #else
169
135
Status MainLoopPosix::RunImpl::Poll () {
170
136
read_fds.clear ();
171
137
172
- sigset_t sigmask = get_sigmask ();
173
-
174
138
for (const auto &fd : loop.m_read_fds ) {
175
139
struct pollfd pfd;
176
140
pfd.fd = fd.first ;
@@ -179,55 +143,39 @@ Status MainLoopPosix::RunImpl::Poll() {
179
143
read_fds.push_back (pfd);
180
144
}
181
145
182
- if (ppoll (read_fds.data (), read_fds.size (), nullptr , &sigmask) == -1 &&
146
+ if (ppoll (read_fds.data (), read_fds.size (),
147
+ /* timeout=*/ nullptr ,
148
+ /* sigmask=*/ nullptr ) == -1 &&
183
149
errno != EINTR)
184
150
return Status (errno, eErrorTypePOSIX);
185
151
186
152
return Status ();
187
153
}
188
- #endif
189
154
190
- void MainLoopPosix::RunImpl::ProcessEvents () {
191
- #ifdef __ANDROID__
192
- // Collect first all readable file descriptors into a separate vector and
193
- // then iterate over it to invoke callbacks. Iterating directly over
194
- // loop.m_read_fds is not possible because the callbacks can modify the
195
- // container which could invalidate the iterator.
196
- std::vector<IOObject::WaitableHandle> fds;
197
- for (const auto &fd : loop.m_read_fds )
198
- if (FD_ISSET (fd.first , &read_fd_set))
199
- fds.push_back (fd.first );
200
-
201
- for (const auto &handle : fds) {
202
- #else
155
+ void MainLoopPosix::RunImpl::ProcessReadEvents () {
203
156
for (const auto &fd : read_fds) {
204
157
if ((fd.revents & (POLLIN | POLLHUP)) == 0 )
205
158
continue ;
206
159
IOObject::WaitableHandle handle = fd.fd ;
207
- #endif
208
160
if (loop.m_terminate_request )
209
161
return ;
210
162
211
163
loop.ProcessReadObject (handle);
212
164
}
213
-
214
- std::vector<int > signals;
215
- for (const auto &entry : loop.m_signals )
216
- if (g_signal_flags[entry.first ] != 0 )
217
- signals.push_back (entry.first );
218
-
219
- for (const auto &signal : signals) {
220
- if (loop.m_terminate_request )
221
- return ;
222
- g_signal_flags[signal ] = 0 ;
223
- loop.ProcessSignal (signal );
224
- }
225
165
}
226
166
#endif
227
167
228
168
MainLoopPosix::MainLoopPosix () : m_triggering(false ) {
229
169
Status error = m_trigger_pipe.CreateNew (/* child_process_inherit=*/ false );
230
170
assert (error.Success ());
171
+
172
+ // Make the write end of the pipe non-blocking.
173
+ int result = fcntl (m_trigger_pipe.GetWriteFileDescriptor (), F_SETFL,
174
+ fcntl (m_trigger_pipe.GetWriteFileDescriptor (), F_GETFL) |
175
+ O_NONBLOCK);
176
+ assert (result == 0 );
177
+ UNUSED_IF_ASSERT_DISABLED (result);
178
+
231
179
const int trigger_pipe_fd = m_trigger_pipe.GetReadFileDescriptor ();
232
180
m_read_fds.insert ({trigger_pipe_fd, [trigger_pipe_fd](MainLoopBase &loop) {
233
181
char c;
@@ -295,26 +243,17 @@ MainLoopPosix::RegisterSignal(int signo, const Callback &callback,
295
243
sigaddset (&new_action.sa_mask , signo);
296
244
sigset_t old_set;
297
245
298
- g_signal_flags[signo] = 0 ;
246
+ // Set signal info before installing the signal handler!
247
+ g_signal_info[signo].pipe_fd = m_trigger_pipe.GetWriteFileDescriptor ();
248
+ g_signal_info[signo].flag = 0 ;
299
249
300
250
// Even if using kqueue, the signal handler will still be invoked, so it's
301
251
// important to replace it with our "benign" handler.
302
252
int ret = sigaction (signo, &new_action, &info.old_action );
303
253
UNUSED_IF_ASSERT_DISABLED (ret);
304
254
assert (ret == 0 && " sigaction failed" );
305
255
306
- #if HAVE_SYS_EVENT_H
307
- struct kevent ev;
308
- EV_SET (&ev, signo, EVFILT_SIGNAL, EV_ADD, 0 , 0 , 0 );
309
- ret = kevent (m_kqueue, &ev, 1 , nullptr , 0 , nullptr );
310
- assert (ret == 0 );
311
- #endif
312
-
313
- // If we're using kqueue, the signal needs to be unblocked in order to
314
- // receive it. If using pselect/ppoll, we need to block it, and later unblock
315
- // it as a part of the system call.
316
- ret = pthread_sigmask (HAVE_SYS_EVENT_H ? SIG_UNBLOCK : SIG_BLOCK,
317
- &new_action.sa_mask , &old_set);
256
+ ret = pthread_sigmask (SIG_UNBLOCK, &new_action.sa_mask , &old_set);
318
257
assert (ret == 0 && " pthread_sigmask failed" );
319
258
info.was_blocked = sigismember (&old_set, signo);
320
259
auto insert_ret = m_signals.insert ({signo, info});
@@ -349,14 +288,8 @@ void MainLoopPosix::UnregisterSignal(
349
288
assert (ret == 0 );
350
289
UNUSED_IF_ASSERT_DISABLED (ret);
351
290
352
- #if HAVE_SYS_EVENT_H
353
- struct kevent ev;
354
- EV_SET (&ev, signo, EVFILT_SIGNAL, EV_DELETE, 0 , 0 , 0 );
355
- ret = kevent (m_kqueue, &ev, 1 , nullptr , 0 , nullptr );
356
- assert (ret == 0 );
357
- #endif
358
-
359
291
m_signals.erase (it);
292
+ g_signal_info[signo] = {};
360
293
}
361
294
362
295
Status MainLoopPosix::Run () {
@@ -370,7 +303,9 @@ Status MainLoopPosix::Run() {
370
303
if (error.Fail ())
371
304
return error;
372
305
373
- impl.ProcessEvents ();
306
+ impl.ProcessReadEvents ();
307
+
308
+ ProcessSignals ();
374
309
375
310
m_triggering = false ;
376
311
ProcessPendingCallbacks ();
@@ -384,6 +319,21 @@ void MainLoopPosix::ProcessReadObject(IOObject::WaitableHandle handle) {
384
319
it->second (*this ); // Do the work
385
320
}
386
321
322
+ void MainLoopPosix::ProcessSignals () {
323
+ std::vector<int > signals;
324
+ for (const auto &entry : m_signals)
325
+ if (g_signal_info[entry.first ].flag != 0 )
326
+ signals.push_back (entry.first );
327
+
328
+ for (const auto &signal : signals) {
329
+ if (m_terminate_request)
330
+ return ;
331
+
332
+ g_signal_info[signal ].flag = 0 ;
333
+ ProcessSignal (signal );
334
+ }
335
+ }
336
+
387
337
void MainLoopPosix::ProcessSignal (int signo) {
388
338
auto it = m_signals.find (signo);
389
339
if (it != m_signals.end ()) {
0 commit comments