[Xcb] [Patch] Fix busy-loop on BSD

Josh Triplett josh at joshtriplett.org
Thu Mar 1 15:29:03 PST 2012


On Thu, Mar 01, 2012 at 09:29:58PM +0100, Uli Schlachter wrote:
> On 01.03.2012 21:14, Josh Triplett wrote:
> > On Thu, Mar 01, 2012 at 08:50:19PM +0100, Uli Schlachter wrote:
> >> attached is a patch with a relatively verbose commit message. I tested this on
> >> one of my university's FreeBSD boxes (with quite a patches userland). I were
> >> able to reproduce the original problem and the patch made it go away.
> >>
> >> At first I wanted to do just what Josh suggested. However, read_block() could
> >> busy loop, too. This would happen if just the first part of an event or reply is
> >> received while the rest of it is stuck somewhere. While this should never occur
> >> in any real world scenarios, it still means that using MSG_WAITALL on a
> >> non-blocking socket is always wrong.
> > 
> > As far as I can tell, read_block will always wait until it reads the
> > requested amount of data.  If recv returns with less than the requested
> > amount of data, read_block will wait for more data and call recv again.
> > Given that, how could MSG_WAITALL cause you to block in the kernel in
> > any situation where you wouldn't just loop in userspace?
> 
> The problem isn't that something gets struck in kernel.
> 
> So let's say read_block() wants to read 100 bytes from the connection, but the
> TCP socket has only 30 bytes ready. recv() with MSG_WAITALL will fail on BSD and
> not return any data, because non-blocking socket + MSG_WAITALL = exactly this
> behavior.
> Next, read_block() will call poll(). This immediately returns, too, because the
> socket is readable (after all, there are 30 bytes ready to be read) and the
> whole loop begins again.
> 
> So this will do a busy loop until all of the 100 bytes can be read. I am not
> saying this will block.
> 
> So the summary still is: "On BSD, MSG_WAITALL is completely unusable on a
> non-blocking socket and never the right thing to do"
> 
> I hope this makes it clearer what I meant.

This makes much more sense now.  I had assumed that on a non-blocking
socket, MSG_WAITALL would wait for the full amount of data, rather than
returning with none and producing a busywait.  Given that, removing both
instances of MSG_WAITALL seems correct.

- Josh Triplett


More information about the Xcb mailing list