classification
Title: Fail to create _SelectorTransport with unbound socket
Type: behavior Stage: resolved
Components: asyncio Versions: Python 3.9
process
Status: closed Resolution: duplicate
Dependencies: Superseder: Can't receive replies from multicast UDP with asyncio
View: 31922
Assigned To: Nosy List: Paul McGuire, gvanrossum, vstinner, yselivanov
Priority: normal Keywords: patch

Created on 2016-08-21 10:40 by Paul McGuire, last changed 2019-12-06 18:57 by vstinner. This issue is now closed.

Files
File name Uploaded Description Edit
ptm_27822.patch Paul McGuire, 2016-08-21 20:29 Patch for Lib/asyncio/selector_events.py
Messages (6)
msg273290 - (view) Author: Paul McGuire (Paul McGuire) Date: 2016-08-21 10:40
In writing a simple UDP client using asyncio, I tripped over a call to getsockname() in the _SelectorTransport class in asyncio/selector_events.py.


    def __init__(self, loop, sock, protocol, extra=None, server=None):
        super().__init__(extra, loop)
        self._extra['socket'] = sock
        self._extra['sockname'] = sock.getsockname()

Since this is a sending-only client, the socket does not get bound to an address. On Linux, this is not a problem; getsockname() will return ('0.0.0.0', 0) for IPV4, ('::', 0, 0, 0) for IPV6, and so on. But on Windows, a socket that is not bound to an address will raise this error when getsockname() is called:

    OSError: [WinError 10022] An invalid argument was supplied

This forces me to write a wrapper for the socket to intercept getsockname() and return None.

In asyncio/proactor_events.py, this is guarded against, with this code in the _ProactorSocketTransport class:

        try:
            self._extra['sockname'] = sock.getsockname()
        except (socket.error, AttributeError):
            if self._loop.get_debug():
                logger.warning("getsockname() failed on %r",
                             sock, exc_info=True)


Please add similar guarding code to the _SelectorTransport class in asyncio/selector_events.py.
msg273292 - (view) Author: Paul McGuire (Paul McGuire) Date: 2016-08-21 10:47
To clarify how I'm using a socket without a bound address, I am specifying the destination address in the call to transport.sendto(), so there is no address on the socket itself, hence getsockname() fails.
msg273294 - (view) Author: Paul McGuire (Paul McGuire) Date: 2016-08-21 11:28
(issue applies to both 3.5.2 and 3.6)
msg273311 - (view) Author: Guido van Rossum (gvanrossum) * (Python committer) Date: 2016-08-21 19:24
Can you supply a patch yourself?

--Guido (mobile)
msg273316 - (view) Author: Paul McGuire (Paul McGuire) Date: 2016-08-21 20:29
Patch file attached.
msg357937 - (view) Author: STINNER Victor (vstinner) * (Python committer) Date: 2019-12-06 18:57
> In writing a simple UDP client using asyncio, I tripped over a call to getsockname() in the _SelectorTransport class in asyncio/selector_events.py. (...)

This bug has been fixed recently by:

commit 63deaa5b70108ef441c57728322da6b4321db4fc
Author: Vincent Michel <vxgmichel@gmail.com>
Date:   Tue May 7 19:18:49 2019 +0200

    bpo-31922: Do not connect UDP sockets when broadcast is allowed (GH-423)


Extract of the change:

diff --git a/Lib/asyncio/selector_events.py b/Lib/asyncio/selector_events.py
index 93b6889509..29968214f8 100644
--- a/Lib/asyncio/selector_events.py
+++ b/Lib/asyncio/selector_events.py
@@ -587,7 +587,10 @@ class _SelectorTransport(transports._FlowControlMixin,
     def __init__(self, loop, sock, protocol, extra=None, server=None):
         super().__init__(extra, loop)
         self._extra['socket'] = sock
-        self._extra['sockname'] = sock.getsockname()
+        try:
+            self._extra['sockname'] = sock.getsockname()
+        except OSError:
+            self._extra['sockname'] = None
         if 'peername' not in self._extra:
             try:
                 self._extra['peername'] = sock.getpeername()


Thanks for your contribution and your proposed patch Paul McGuire! Sorry for the late reply. I mark this change as a duplicate of bpo-31922.
History
Date User Action Args
2019-12-06 18:57:39vstinnersetstatus: open -> closed
versions: + Python 3.9, - Python 3.5, Python 3.6
superseder: Can't receive replies from multicast UDP with asyncio
messages: + msg357937

resolution: duplicate
stage: resolved
2016-08-21 20:29:07Paul McGuiresetfiles: + ptm_27822.patch
keywords: + patch
messages: + msg273316
2016-08-21 19:24:52gvanrossumsetmessages: + msg273311
2016-08-21 11:28:50Paul McGuiresetmessages: + msg273294
versions: + Python 3.5
2016-08-21 10:47:24Paul McGuiresetmessages: + msg273292
2016-08-21 10:40:53Paul McGuirecreate