Fix a busy loop on BSD and Mac OS
authorUli Schlachter <psychon@znc.in>
Thu, 1 Mar 2012 19:26:39 +0000 (20:26 +0100)
committerUli Schlachter <psychon@znc.in>
Thu, 8 Mar 2012 14:40:35 +0000 (15:40 +0100)
commit236f914ea7205f5f74e87fcc1b06d87bd0789a7a
tree4ec355016563c4de72b7b4ef43b8a2e9eac2a902
parent9061ee45b8dbe5431c23e3f628089d703ccad0b1
Fix a busy loop on BSD and Mac OS

On FreeBSD MSG_WAITALL on a non-blocking socket fails immediately if less bytes
than were asked for are available. This is different than the behavior on linux
where as many bytes as are available are returned in this case. Other OS
apparently follow the FreeBSD behavior.

_xcb_in_read() is used to fill xcb's read buffer, thus this function will call
recv() with a big length argument (xcb's read buffer is by default 16 KiB
large). That many bytes are highly unlikely to be available in the kernel
buffer.

This means that _xcb_in_read() always failed on FreeBSD. Since the socket was
still signaled as readable by poll(), this bug even resulted in a busy loop.

The same issue is present in read_block(), but here it is slightly different.
read_block() is called when we read the first few bytes of an event or a reply,
so that we already know its length. This means that we should be able to use
MSG_WAITALL here, because we know how many bytes there have to be.

However, that function could busy loop, too, when only the first few bytes of
the packet were sent while the rest is stuck somewhere on the way to us. Thus,
MSG_WAITALL should be removed here, too.

Thanks to Christoph Egger from Debian for noticing the problem, doing all the
necessary debugging and figuring out what the problem was! This patch is 99%
from debian. Thanks for all the work.

This bug was introduced in commit 2dcf8b025be88a25d4333abdc28d425b88238d96.

This commit also reverts commit 9061ee45b8dbe5431c23e3f628089d703ccad0b1.

Fixes: https://bugs.freedesktop.org/show_bug.cgi?id=45776

Signed-off-by: Uli Schlachter <psychon@znc.in>
Reviewed-by: Josh Triplett <josh@joshtriplett.org>
src/xcb_in.c