Skip to content
Browse files

Fixed Issue #155 -- gevent.os.posix_read/posix_write don't honor non-…

…blocking FD's.

Implemented unit tests in test__os.py: test_o_nonblock_read() and test_o_nonblock_write()
  • Loading branch information...
1 parent c69c5b9 commit 10e329ce931f227ee1b36efd91fc317cf222de8d @vitaly-krugl committed Sep 15, 2012
Showing with 69 additions and 4 deletions.
  1. +10 −4 gevent/os.py
  2. +59 −0 greentest/test__os.py
View
14 gevent/os.py
@@ -48,21 +48,24 @@ def posix_read(fd, n):
hub, event = None, None
while True:
flags = _map_errors(fcntl.fcntl, fd, fcntl.F_GETFL, 0)
- if not flags & os.O_NONBLOCK:
+ original_nonblock_option = flags & os.O_NONBLOCK
+ if not original_nonblock_option:
_map_errors(fcntl.fcntl, fd, fcntl.F_SETFL, flags|os.O_NONBLOCK)
try:
return _read(fd, n)
except OSError, e:
if e.errno not in ignored_errors:
raise
+ if e.errno == EAGAIN and original_nonblock_option:
+ raise
sys.exc_clear()
finally:
# Be sure to restore the fcntl flags before we switch into the hub.
# Sometimes multiple file descriptors share the same fcntl flags
# (e.g. when using ttys/ptys). Those other file descriptors are
# impacted by our change of flags, so we should restore them
# before any other code can possibly run.
- if not flags & os.O_NONBLOCK:
+ if not original_nonblock_option:
_map_errors(fcntl.fcntl, fd, fcntl.F_SETFL, flags)
if hub is None:
hub = get_hub()
@@ -76,17 +79,20 @@ def posix_write(fd, buf):
hub, event = None, None
while True:
flags = _map_errors(fcntl.fcntl, fd, fcntl.F_GETFL, 0)
- if not flags & os.O_NONBLOCK:
+ original_nonblock_option = flags & os.O_NONBLOCK
+ if not original_nonblock_option:
_map_errors(fcntl.fcntl, fd, fcntl.F_SETFL, flags|os.O_NONBLOCK)
try:
return _write(fd, buf)
except OSError, e:
if e.errno not in ignored_errors:
raise
+ if e.errno == EAGAIN and original_nonblock_option:
+ raise
sys.exc_clear()
finally:
# See note in posix_read().
- if not flags & os.O_NONBLOCK:
+ if not original_nonblock_option:
_map_errors(fcntl.fcntl, fd, fcntl.F_SETFL, flags)
if hub is None:
hub = get_hub()
View
59 greentest/test__os.py
@@ -8,6 +8,11 @@
except ImportError:
fcntl = None
+try:
+ import errno
+except ImportError:
+ errno = None
+
class TestOS(TestCase):
@@ -57,6 +62,60 @@ def test_fd_flags_restored(self):
flags = fcntl.fcntl(w, fcntl.F_GETFL, 0)
assert not flags & os.O_NONBLOCK
+ def test_o_nonblock_read(self):
+ if fcntl is None or errno is None:
+ return
+ r, w = os.pipe()
+
+ rflags = fcntl.fcntl(r, fcntl.F_GETFL, 0)
+ fcntl.fcntl(r, fcntl.F_SETFL, rflags|os.O_NONBLOCK)
+
+ gotEAGAIN = False
+ try:
+ os.read(r, 3)
+ except OSError, e:
+ if e.errno != errno.EAGAIN:
+ raise
+
+ gotEAGAIN = True
+
+ assert gotEAGAIN
+
+ os.write(w, "foo")
+ data = os.read(r, 3)
+ assert data == "foo"
+
+ gotEAGAIN = False
+ try:
+ os.read(r, 3)
+ except OSError, e:
+ if e.errno != errno.EAGAIN:
+ raise
+
+ gotEAGAIN = True
+
+ assert gotEAGAIN
+
+ def test_o_nonblock_write(self):
+ if fcntl is None or errno is None:
+ return
+ r, w = os.pipe()
+
+ wflags = fcntl.fcntl(r, fcntl.F_GETFL, 0)
+ fcntl.fcntl(w, fcntl.F_SETFL, wflags|os.O_NONBLOCK)
+ data = "d" * 1000000
+ gotEAGAIN = False
+ try:
+ os.write(w, data)
+ os.write(w, data)
+ except OSError, e:
+ if e.errno != errno.EAGAIN:
+ raise
+
+ gotEAGAIN = True
+
+ assert gotEAGAIN
+
if __name__ == '__main__':
main()

0 comments on commit 10e329c

Please sign in to comment.
Something went wrong with that request. Please try again.