Can a sock.recvfrom
ever raise a BlockingIOError
from a reader? Such as below
sock.setblocking(False)
def reader()
try:
(data, addr) = sock.recvfrom(512)
except BlockingIOError:
# Can this ever be raised?
loop.add_reader(sock.fileno(), reader)
Similarly, can a sock.send
ever raise a BlockingIOError
from a writer?
sock.setblocking(False)
def writer()
try:
bytes_sent = sock.send(data)
except BlockingIOError:
# Can this ever be raised?
loop.add_writer(sock.fileno(), writer)
I've experimented by trying to send/recv a fair bit of data, but it's never happened so far. Can it never actually happen, logically? If it can happen, under what circumstances?
Can [
BlockingIOError
in an asyncio reader] never actually happen, logically? If if it can happen, under what circumstances?
The answer to this question will almost certainly be system-dependent. Python itself doesn't provide any guarantees on the matter: functions like os.read
and socket.recv
just check the value returned by the underlying system call and, if it indicates an error, go on to convert the system-provided error to a Python exception.
So the question boils down to whether a read from a socket can fail with EAGAIN
or equivalent if a preceding poll/select has indicated that it was readable (and the equivalent for writes). While that certainly sounds like an abnormal situation, the select(2)
man page explicitly warns of it under BUGS:
Under Linux,
select()
may report a socket file descriptor as "ready for reading", while nevertheless a subsequent read blocks. This could for example happen when data has arrived but upon examination has wrong checksum and is discarded. There may be other circumstances in which a file descriptor is spuriously reported as ready. Thus it may be safer to useO_NONBLOCK
on sockets that should not block.
With non-blocking sockets, one should read "nevertheless a subsequent read blocks" as "nevertheless a subsequent read fails with EAGAIN
", and the warning applies to this question. The issue is not specific to select()
either; the poll(2)
man page also mentions spurious wakeups in its BUGS section, referring to the select(2)
manual for details.
In other words, portable code should not rely on reads from "readable" sockets never raising BlockingIOError
. Asyncio doesn't rely on it: it reacts to EAGAIN
by simply not completing the future , and thereby re-suspending the coroutine that awaits the read.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.