Bug 3020 - Mac OS X/Darwin incorrectly shows read sockets ready when they aren't
Summary: Mac OS X/Darwin incorrectly shows read sockets ready when they aren't
Alias: None
Product: rsync
Classification: Unclassified
Component: core (show other bugs)
Version: 2.6.5
Hardware: PPC Mac OS X
: P3 critical (vote)
Target Milestone: ---
Assignee: Wayne Davison
QA Contact: Rsync QA Contact
Depends on:
Reported: 2005-08-20 12:06 UTC by Kevin Day
Modified: 2006-03-12 02:56 UTC (History)
0 users

See Also:


Note You need to log in before you can comment on or make changes to this bug.
Description Kevin Day 2005-08-20 12:06:18 UTC
Occasionally (especially when the parent process has alarm signals running, which get inherited to the 
child rsync process, but even when no signal activity is happening) Mac OS X will return that a read 
socket is ready to be read from, but 0 bytes are returned from a read() call.

Rsync assumes this means the connection is closed, which tears the session down. On OS X this seems 
not to be true. This only seems to occur on very busy systems, it's difficult to reproduce on a 
development machine, but nearly impossible to work around on a busy server. This bug also appears 
only to be present in OS X 10.4, reverting to 10.3 is fine.

This patch has worked fine for me for a few weeks now, which changed things from "unusable on OS X" 
to "works flawlessly". I think it's safe to commit, I don't know of any OS that returns 0 on a read without 
setting errno when something really is wrong.

--- io.c.orig   2005-08-20 18:44:34.000000000 +0000
+++ io.c        2005-08-20 19:02:37.000000000 +0000
@@ -570,7 +570,7 @@
                n = read(fd, buf, len);
-               if (n <= 0) {
+               if ((n <= 0) && errno) {
                        if (n == 0)
                                whine_about_eof(fd); /* Doesn't return. */
                        if (errno == EINTR || errno == EWOULDBLOCK
Comment 1 Wayne Davison 2005-08-23 10:43:48 UTC
This is a bug in MacOS, then.  A return of 0 from read() indicates end-of-file,
and errno is not guaranteed to be any particular value in that case (I've tested
that it is often 0).  If MacOS has a no-data situation such as that, they should
probably be returning -1 with errno set to EAGAIN.