-
-
Notifications
You must be signed in to change notification settings - Fork 30.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
SocketIO should return None on EWOULDBLOCK #54063
Comments
SocketIO claims to implement RawIOBase, but it lets blocking IO errors pass through on non-blocking sockets: >>> s = socket.create_connection(("python.org", 80)); s.settimeout(0.0)
>>> f = s.makefile("rb", buffering=0)
>>> f.readinto(bytearray(10))
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/home/antoine/py3k/nntp-9360/Lib/socket.py", line 228, in readinto
return self._sock.recv_into(b)
socket.error: [Errno 11] Resource temporarily unavailable Instead, readinto() should detect the blocking condition (EAGAIN / EWOULDBLOCK) and return None (same for write(), I imagine). There also seems to be a problem in the default read() implementation in RawIOBase, which doesn't accept a possible None result from readinto(): >>> f.readinto = lambda x: None
>>> f.read(1)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'NoneType' object cannot be interpreted as an integer (the RawIOBase docs themselves don't mention that readinto() can return None, but it's the only logical possibility: catching EWOULDBLOCK in read() but not in readinto() wouldn't make sense) |
The problem with RawIOBase.read is fixed in r84814. |
Here is a patch. |
I've never used socket.socket.makefile so I'm not sure, but its documentation says:
If the statement is there because EAGAIN/EWOULDBLOCK were originally raised then it should be removed, otherwise I question whether makefile() is actually supposed to support non-blocking sockets in the first place.
io.RawIOBase.readinto doc says:
...so returning 0 instead of None looks more natural to me. >>> open('xxx', 'w').write('')
0 I've also noticed that socket.SocketIO.readinto has a while loop which continues in case of EINTR and that's something which should be removed in case makefile() actually intends to support non-blocking sockets. |
Le mardi 14 septembre 2010 à 23:19 +0000, Giampaolo Rodola' a écrit :
If it wasn't supposed to, we can add that support.
Well, since it claims to implement RawIOBase, it should provide a RawIOBase-like behaviour :) Returning None is what raw I/O objects are supposed to do when they fail reading or writing even a single byte. It is designed and documented as such. (the readinto() doc you mentioned lacked that precision, but I've just fixed it) The reason None is returned (rather than 0 or b'') is so that the caller can recognize the situation and take appropriate measures. ["file-like behaviour"]
Non-blocking files exist: >>> import fcntl, os, io
>>> r, w = os.pipe()
>>> fcntl.fcntl(r, fcntl.F_SETFL, os.O_NONBLOCK)
0
>>> os.read(r, 2)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
OSError: [Errno 11] Resource temporarily unavailable (It seems that on regular files O_NONBLOCK may not have an effect; not under Linux anyway) |
Of course, I should have been more clear.
From http://docs.python.org/dev/library/io.html#module-io about io.BufferedIOBase.readinto()
This is valid for BufferedReader, BufferWriter and BufferIOBase classes in various methods while io.RawIOBase.write() and io.RawIOBase.read() return None instead. Shouldn't they raise BlockingIOError as well? Why do they return None? |
Indeed. It would probably be a nice addition, assuming it is portable
Well, that's how it was decided when the new IO lib was designed. |
Was committed in r84887. |
Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.
Show more details
GitHub fields:
bugs.python.org fields:
The text was updated successfully, but these errors were encountered: