1717#include < cerrno>
1818#include < csignal>
1919#include < ctime>
20+ #include < fcntl.h>
2021#include < vector>
2122
2223// 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.
2625
2726#if HAVE_SYS_EVENT_H
2827#include < sys/event.h>
29- #elif defined(__ANDROID__)
30- #include < sys/syscall.h>
3128#else
3229#include < poll.h>
3330#endif
3431
3532using namespace lldb ;
3633using namespace lldb_private ;
3734
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];
3944
4045static void SignalHandler (int signo, siginfo_t *info, void *) {
4146 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));
4368}
4469
4570class MainLoopPosix ::RunImpl {
@@ -48,7 +73,7 @@ class MainLoopPosix::RunImpl {
4873 ~RunImpl () = default ;
4974
5075 Status Poll ();
51- void ProcessEvents ();
76+ void ProcessReadEvents ();
5277
5378private:
5479 MainLoopPosix &loop;
@@ -58,15 +83,9 @@ class MainLoopPosix::RunImpl {
5883 struct kevent out_events[4 ];
5984 int num_events = -1 ;
6085
61- #else
62- #ifdef __ANDROID__
63- fd_set read_fd_set;
6486#else
6587 std::vector<struct pollfd > read_fds;
6688#endif
67-
68- sigset_t get_sigmask ();
69- #endif
7089};
7190
7291#if HAVE_SYS_EVENT_H
@@ -94,7 +113,7 @@ Status MainLoopPosix::RunImpl::Poll() {
94113 return Status ();
95114}
96115
97- void MainLoopPosix::RunImpl::ProcessEvents () {
116+ void MainLoopPosix::RunImpl::ProcessReadEvents () {
98117 assert (num_events >= 0 );
99118 for (int i = 0 ; i < num_events; ++i) {
100119 if (loop.m_terminate_request )
@@ -103,74 +122,19 @@ void MainLoopPosix::RunImpl::ProcessEvents() {
103122 case EVFILT_READ:
104123 loop.ProcessReadObject (out_events[i].ident );
105124 break ;
106- case EVFILT_SIGNAL:
107- loop.ProcessSignal (out_events[i].ident );
108- break ;
109125 default :
110126 llvm_unreachable (" Unknown event" );
111127 }
112128 }
113129}
114130#else
115131MainLoopPosix::RunImpl::RunImpl (MainLoopPosix &loop) : loop(loop) {
116- #ifndef __ANDROID__
117132 read_fds.reserve (loop.m_read_fds .size ());
118- #endif
119133}
120134
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
169135Status MainLoopPosix::RunImpl::Poll () {
170136 read_fds.clear ();
171137
172- sigset_t sigmask = get_sigmask ();
173-
174138 for (const auto &fd : loop.m_read_fds ) {
175139 struct pollfd pfd;
176140 pfd.fd = fd.first ;
@@ -179,55 +143,39 @@ Status MainLoopPosix::RunImpl::Poll() {
179143 read_fds.push_back (pfd);
180144 }
181145
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 &&
183149 errno != EINTR)
184150 return Status (errno, eErrorTypePOSIX);
185151
186152 return Status ();
187153}
188- #endif
189154
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 () {
203156 for (const auto &fd : read_fds) {
204157 if ((fd.revents & (POLLIN | POLLHUP)) == 0 )
205158 continue ;
206159 IOObject::WaitableHandle handle = fd.fd ;
207- #endif
208160 if (loop.m_terminate_request )
209161 return ;
210162
211163 loop.ProcessReadObject (handle);
212164 }
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- }
225165}
226166#endif
227167
228168MainLoopPosix::MainLoopPosix () : m_triggering(false ) {
229169 Status error = m_trigger_pipe.CreateNew (/* child_process_inherit=*/ false );
230170 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+
231179 const int trigger_pipe_fd = m_trigger_pipe.GetReadFileDescriptor ();
232180 m_read_fds.insert ({trigger_pipe_fd, [trigger_pipe_fd](MainLoopBase &loop) {
233181 char c;
@@ -295,26 +243,17 @@ MainLoopPosix::RegisterSignal(int signo, const Callback &callback,
295243 sigaddset (&new_action.sa_mask , signo);
296244 sigset_t old_set;
297245
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 ;
299249
300250 // Even if using kqueue, the signal handler will still be invoked, so it's
301251 // important to replace it with our "benign" handler.
302252 int ret = sigaction (signo, &new_action, &info.old_action );
303253 UNUSED_IF_ASSERT_DISABLED (ret);
304254 assert (ret == 0 && " sigaction failed" );
305255
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);
318257 assert (ret == 0 && " pthread_sigmask failed" );
319258 info.was_blocked = sigismember (&old_set, signo);
320259 auto insert_ret = m_signals.insert ({signo, info});
@@ -349,14 +288,8 @@ void MainLoopPosix::UnregisterSignal(
349288 assert (ret == 0 );
350289 UNUSED_IF_ASSERT_DISABLED (ret);
351290
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-
359291 m_signals.erase (it);
292+ g_signal_info[signo] = {};
360293}
361294
362295Status MainLoopPosix::Run () {
@@ -370,7 +303,9 @@ Status MainLoopPosix::Run() {
370303 if (error.Fail ())
371304 return error;
372305
373- impl.ProcessEvents ();
306+ impl.ProcessReadEvents ();
307+
308+ ProcessSignals ();
374309
375310 m_triggering = false ;
376311 ProcessPendingCallbacks ();
@@ -384,6 +319,21 @@ void MainLoopPosix::ProcessReadObject(IOObject::WaitableHandle handle) {
384319 it->second (*this ); // Do the work
385320}
386321
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+
387337void MainLoopPosix::ProcessSignal (int signo) {
388338 auto it = m_signals.find (signo);
389339 if (it != m_signals.end ()) {
0 commit comments