diff options
author | Martin Dørum <martid0311@gmail.com> | 2019-05-19 16:05:08 +0200 |
---|---|---|
committer | Martin Dørum <martid0311@gmail.com> | 2019-05-19 16:05:08 +0200 |
commit | 21324989b7e121c008a2c4fdf98547541cbf7b83 (patch) | |
tree | bfb1c34c30e9294e12e225fcd4e411f00df687c1 | |
parent | 656c08c5429a3cf53e7abd7fc56cd3c3a79c0f64 (diff) |
Handle EINTR from recvmsg in _xcb_in_read
I have a GTK application which occasionally crashes with an "interrupted
system call" g_message from gdk. After a lot of debugging, I've found
that the call to recvmsg in _xcb_in_read occasionally fails with EINTR,
and instead of retrying the system call, xcb would just shut down the
connection.
This change makes _xcb_in_read treat EINTR the same as it would treat
EAGAIN; it returns 1 and libX11 ends up calling xcb_poll_for_event
again (from what I have understood).
I have spoken with a few people who think recvmsg failing with EINTR in
this case shouldn't ever happen, and I don't know enough to agree or
disagree with that. In case anyone wants to dig further and try to
figure out why the recvmsg call sometimes fails with EINTR, here's the
backtrace from inside of _xcb_in_read where that happened:
Thread 1 "beanbar" hit Breakpoint 1, _xcb_in_read (c=c@entry=0x55ecbe4aba80) at xcb_in.c:1059
1059 fprintf(stderr, "Hello World am %s:%i, errno is %s\n", __FILE__, __LINE__, strerror(errno));
(gdb) bt
0 0x00007fa48fa48639 in _xcb_in_read (c=c@entry=0x55ecbe4aba80) at xcb_in.c:1059
1 0x00007fa48fa489d8 in poll_for_next_event (c=0x55ecbe4aba80, queued=queued@entry=0) at xcb_in.c:352
2 0x00007fa48fa48a3d in poll_for_next_event (queued=0, c=<optimized out>) at xcb_in.c:722
3 0x00007fa48fa48a3d in xcb_poll_for_event (c=<optimized out>) at xcb_in.c:722
4 0x00007fa4908d1b7e in poll_for_event (dpy=dpy@entry=0x55ecbe4a9730, queued_only=queued_only@entry=0) at xcb_io.c:245
5 0x00007fa4908d1cf0 in poll_for_response (dpy=dpy@entry=0x55ecbe4a9730) at xcb_io.c:303
6 0x00007fa4908d1fed in _XEventsQueued (mode=2, dpy=0x55ecbe4a9730) at xcb_io.c:363
7 0x00007fa4908d1fed in _XEventsQueued (dpy=dpy@entry=0x55ecbe4a9730, mode=mode@entry=2) at xcb_io.c:344
8 0x00007fa4908c3d47 in XPending (dpy=0x55ecbe4a9730) at Pending.c:55
9 0x00007fa493cadbc7 in () at /usr/lib/libgdk-3.so.0
10 0x00007fa49234d08a in g_main_context_prepare () at /usr/lib/libglib-2.0.so.0
11 0x00007fa49234d6e6 in () at /usr/lib/libglib-2.0.so.0
12 0x00007fa49234d8ae in g_main_context_iteration () at /usr/lib/libglib-2.0.so.0
13 0x00007fa4938b920e in g_application_run () at /usr/lib/libgio-2.0.so.0
14 0x000055ecbc820af4 in main (argc=1, argv=0x7ffd06238098) at src/main.c:190
Signed-off-by: Martin Dørum <martid0311@gmail.com>
-rw-r--r-- | src/xcb_in.c | 2 |
1 files changed, 1 insertions, 1 deletions
diff --git a/src/xcb_in.c b/src/xcb_in.c index 58fe896..733d749 100644 --- a/src/xcb_in.c +++ b/src/xcb_in.c @@ -1051,7 +1051,7 @@ int _xcb_in_read(xcb_connection_t *c) } #endif #ifndef _WIN32 - if((n > 0) || (n < 0 && errno == EAGAIN)) + if((n > 0) || (n < 0 && (errno == EAGAIN || errno == EINTR))) #else if((n > 0) || (n < 0 && WSAGetLastError() == WSAEWOULDBLOCK)) #endif /* !_WIN32 */ |