88import _overlapped
99import _winapi
1010import errno
11- from functools import partial
1211import math
1312import msvcrt
1413import socket
@@ -460,24 +459,20 @@ def finish_socket_func(trans, key, ov):
460459 try:
461460 return ov.getresult()
462461 except OSError as exc:
462+ # ERROR_PORT_UNREACHABLE is reported by WSARecvFrom when the
463+ # same socket was previously used to send to an address that
464+ # isn't listening (gh-91227). Surface it as a
465+ # ConnectionResetError, like the other recoverable codes here,
466+ # so it propagates to the caller the same way a plain
467+ # socket.recvfrom() already does on SelectorEventLoop, instead
468+ # of being silently swallowed.
463469 if exc.winerror in (_overlapped.ERROR_NETNAME_DELETED,
464- _overlapped.ERROR_OPERATION_ABORTED):
470+ _overlapped.ERROR_OPERATION_ABORTED,
471+ _overlapped.ERROR_PORT_UNREACHABLE):
465472 raise ConnectionResetError(*exc.args)
466473 else:
467474 raise
468475
469- @classmethod
470- def _finish_recvfrom(cls, trans, key, ov, *, empty_result):
471- try:
472- return cls.finish_socket_func(trans, key, ov)
473- except OSError as exc:
474- # WSARecvFrom will report ERROR_PORT_UNREACHABLE when the same
475- # socket is used to send to an address that is not listening.
476- if exc.winerror == _overlapped.ERROR_PORT_UNREACHABLE:
477- return empty_result, None
478- else:
479- raise
480-
481476 def recv(self, conn, nbytes, flags=0):
482477 self._register_with_iocp(conn)
483478 ov = _overlapped.Overlapped(NULL)
@@ -512,8 +507,7 @@ def recvfrom(self, conn, nbytes, flags=0):
512507 except BrokenPipeError:
513508 return self._result((b'', None))
514509
515- return self._register(ov, conn, partial(self._finish_recvfrom,
516- empty_result=b''))
510+ return self._register(ov, conn, self.finish_socket_func)
517511
518512 def recvfrom_into(self, conn, buf, nbytes=0):
519513 self._register_with_iocp(conn)
@@ -523,8 +517,7 @@ def recvfrom_into(self, conn, buf, nbytes=0):
523517 except BrokenPipeError:
524518 return self._result((0, None))
525519
526- return self._register(ov, conn, partial(self._finish_recvfrom,
527- empty_result=0))
520+ return self._register(ov, conn, self.finish_socket_func)
528521
529522 def sendto(self, conn, buf, flags=0, addr=None):
530523 self._register_with_iocp(conn)
0 commit comments