Skip to content

Conversation

@Dreamsorcerer
Copy link
Contributor

@Dreamsorcerer Dreamsorcerer commented May 19, 2025

We have a flaky test where, very occasionally on Windows, a request to the server immediately after loop.create_server() gets rejected.

Comparing the code between selector and proactor loops, it appears that the proactor loop would need one more loop iteration than the selector loop, if I'm understanding the code correctly.

The proactor code is nested in a loop registered with call_soon(), so it won't start executing until one loop iteration later than the selector loop does:

def loop(f=None):
try:
if f is not None:
conn, addr = f.result()
if self._debug:
logger.debug("%r got a new connection from %r: %r",
server, addr, conn)
protocol = protocol_factory()
if sslcontext is not None:
self._make_ssl_transport(
conn, protocol, sslcontext, server_side=True,
extra={'peername': addr}, server=server,
ssl_handshake_timeout=ssl_handshake_timeout,
ssl_shutdown_timeout=ssl_shutdown_timeout)
else:
self._make_socket_transport(
conn, protocol,
extra={'peername': addr}, server=server)
if self.is_closed():
return
f = self._proactor.accept(sock)
except OSError as exc:
if sock.fileno() != -1:
self.call_exception_handler({
'message': 'Accept failed on a socket',
'exception': exc,
'socket': trsock.TransportSocket(sock),
})
sock.close()
elif self._debug:
logger.debug("Accept failed on socket %r",
sock, exc_info=True)
except exceptions.CancelledError:
sock.close()
else:
self._accept_futures[sock.fileno()] = f
f.add_done_callback(loop)
self.call_soon(loop)

Compared to:

self._check_closed()
handle = events.Handle(callback, args, self, None)
key = self._selector.get_map().get(fd)
if key is None:
self._selector.register(fd, selectors.EVENT_READ,
(handle, None))
else:
mask, (reader, writer) = key.events, key.data
self._selector.modify(fd, mask | selectors.EVENT_READ,
(handle, writer))
if reader is not None:
reader.cancel()

i.e. selector.register() is called in loop iteration 0, whereas proactor.accept() is called in loop iteration 1.

@Dreamsorcerer Dreamsorcerer changed the title Fix Windows server not accepting requests when returning from loop.create_server() Fix Windows server not accepting requests after returning from loop.create_server() May 19, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant