The problematic section of code looks roughly as follows:
import socket, my_custom_socket_address_getting_module
underlyingSocketFileno = my_custom_socket_address_getting_module.get()
connectedSocket = socket.socket( fileno=underlyingSocketFileno )
clientAddress = connectedSocket.getpeername()
Where "my_custom_socket_address_getting_module" is a custom C extension which returns the address of an open socket on my machine (as a long).
The first two lines seem to work well, and the Python socket object looks sensible (e.g. the fd and other socket properties look correct in the debugger), but trying to call getpeername on the object throws the following exception:
<class 'OSError'>:[WinError 10014] The system detected an invalid pointer address in attempting to use a pointer argument in a call
Since I'm letting Python construct both the Python socket (and presumably the backing OS SOCKET as well), I've no idea where the broken pointer address would be coming from.
I'm fairly confident that the socket address being supplied to Python from my custom module is correct, and that the socket address it returns is valid, as the extension worked perfectly with my old Python version.
This issue started when I moved to a much more recent version of Python (3.6.5) - any ideas as to why this new version would be acting like this? The previous working version was Python 1.5.2 (yes, really).
(OS is Microsoft Windows 8.1 64, Python 3.6.5, built with MSVCC v.1911)
From the Python 3 Docs for the socket.socket constructor:
If fileno is specified, the other arguments are ignored, causing the socket with the specified file descriptor to return.
Maybe this was obvious to the author of the documentation, but it looks like this only works if the socket associated with the fileno you pass in was created by Python. If you are trying to connect to a socket which was opened by an extension module, then Python will create a socket object with the fileno you gave it, but the other socket properties (type, family, protocol) will be set to their default values.
In this case, the socket was an IPv6 socket, but the default for Python sockets is IPv4. Manually specifying the socket type and family resolved the issue.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With