aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorEelco Dolstra <edolstra@gmail.com>2023-01-11 10:48:40 -0800
committerEelco Dolstra <edolstra@gmail.com>2023-01-11 10:48:40 -0800
commit9fc8d00d741d17ff25c0193f182103d00d11582a (patch)
treeb989bcc902fe75b07bc145c3dca3c0eb321732e0 /src
parent6dd8b3b4122d9a4dccf17c00a290349a1509a7d6 (diff)
MonitorFdHup: Make it work on macOS again
It appears that on current macOS versions, our use of poll() to detect client disconnects no longer works. As a workaround, poll() for POLLRDNORM, since this *will* wake up when the client has disconnected. The downside is that it also wakes up when input is available. So just sleep for a bit in that case. This means that on macOS, a client disconnect may take up to a second to be detected, but that's better than not being detected at all. Fixes #7584.
Diffstat (limited to 'src')
-rw-r--r--src/libutil/monitor-fd.hh53
1 files changed, 32 insertions, 21 deletions
diff --git a/src/libutil/monitor-fd.hh b/src/libutil/monitor-fd.hh
index 5ee0b88ef..9518cf8aa 100644
--- a/src/libutil/monitor-fd.hh
+++ b/src/libutil/monitor-fd.hh
@@ -22,27 +22,38 @@ public:
{
thread = std::thread([fd]() {
while (true) {
- /* Wait indefinitely until a POLLHUP occurs. */
- struct pollfd fds[1];
- fds[0].fd = fd;
- /* This shouldn't be necessary, but macOS doesn't seem to
- like a zeroed out events field.
- See rdar://37537852.
- */
- fds[0].events = POLLHUP;
- auto count = poll(fds, 1, -1);
- if (count == -1) abort(); // can't happen
- /* This shouldn't happen, but can on macOS due to a bug.
- See rdar://37550628.
-
- This may eventually need a delay or further
- coordination with the main thread if spinning proves
- too harmful.
- */
- if (count == 0) continue;
- assert(fds[0].revents & POLLHUP);
- triggerInterrupt();
- break;
+ /* Wait indefinitely until a POLLHUP occurs. */
+ struct pollfd fds[1];
+ fds[0].fd = fd;
+ /* Polling for no specific events (i.e. just waiting
+ for an error/hangup) doesn't work on macOS
+ anymore. So wait for read events and ignore
+ them. */
+ fds[0].events =
+ #ifdef __APPLE__
+ POLLRDNORM
+ #else
+ 0
+ #endif
+ ;
+ auto count = poll(fds, 1, -1);
+ if (count == -1) abort(); // can't happen
+ /* This shouldn't happen, but can on macOS due to a bug.
+ See rdar://37550628.
+
+ This may eventually need a delay or further
+ coordination with the main thread if spinning proves
+ too harmful.
+ */
+ if (count == 0) continue;
+ if (fds[0].revents & POLLHUP) {
+ triggerInterrupt();
+ break;
+ }
+ /* This will only happen on macOS. We sleep a bit to
+ avoid waking up too often if the client is sending
+ input. */
+ sleep(1);
}
});
};