[ python-Bugs-805194 ] Inappropriate error received using socket timeout
SourceForge.net
noreply at sourceforge.net
Fri Mar 9 19:49:23 CET 2007
Bugs item #805194, was opened at 2003-09-12 12:56
Message generated for change (Comment added) made by dmeranda
You can respond by visiting:
https://sourceforge.net/tracker/?func=detail&atid=105470&aid=805194&group_id=5470
Please note that this message will contain a full copy of the comment thread,
including the initial issue submission, for this request,
not just the latest update.
Category: Windows
Group: Python 2.3
Status: Open
Resolution: None
Priority: 5
Private: No
Submitted By: Popov (evgeni_popov)
Assigned to: Nobody/Anonymous (nobody)
Summary: Inappropriate error received using socket timeout
Initial Comment:
When using the timeout option with a socket object
(python 2.3), I don't have the same behaviour under
Windows than under Linux / Mac.
Specifically, if trying to connect to an unopened port of
the localhost, I get a timeout exception on Windows
(tested under W2K Server), whereas I get a "111 -
Connection Refused" exception on Linux and "22 - Invalid
Argument" on Mac (OS X).
Even if the error message under Mac is not really
appropriate (someone said to me he got the
right 'Connection Refused' on his MAC), I think that the
behaviour under Linux and Mac is the right one, in that it
sends (quickly) an error message and not timeouting.
Note that when using blocking socket the behaviour is
ok under all platforms: they each return back quickly
a "Connection refused" error message (err codes are
different depending on the platform (61=Mac,
111=Linux, 10061=Windows)). FYI, I don't use firewall or
similar prog on my windows box (but that should not
matter, because it does work in blocking mode, so that
can't be a firewall problem).
I heard that the timeout option was implemented based
on Timothy O'Malley timeoutsocket.py. Then, maybe the
pb can come from the usage of select in the connection
function: select is not asked to get back exceptions in
the returned triple, whereas I think some errors can be
returned back through this mean under Windows
(according to Tip 25 of Jon C. Snader book's "Effective
TCP/IP Programming"). So, by not checking the returned
exceptions, we would miss the "connection refused"
error and get instead the timeout error...
----------------------------------------------------------------------
Comment By: Deron Meranda (dmeranda)
Date: 2007-03-09 13:49
Message:
Logged In: YES
user_id=847188
Originator: NO
Verified that AIX 5.2 works fine, it returns an ECONNREFUSED in
all cases.
Some interesting related links though:
Twisted bug# 2022
http://twistedmatrix.com/trac/ticket/2022
"Non-blocking BSD socket connections" by D.J. Bernstein
http://cr.yp.to/docs/connect.html
There's also an interesting comment in Apache's APR change
notes for APR 0.9 <http://www.apache.org/dist/apr/CHANGES-APR-0.9>
which seems to indicate that perhaps doing a second connect()
is wrong:
"*) Non-blocking connects shouldn't be calling connect a second
time. According to Single Unix, a non-blocking connect has
succeeded when the select pops successfully. It has failed
if the select failed. The second connect was causing 502's
in the httpd-proxy. [John Barbee barbee at veribox.net]"
If the APR comment is correct, then perhaps this is a Python
bug after all??
----------------------------------------------------------------------
Comment By: Deron Meranda (dmeranda)
Date: 2007-03-09 11:53
Message:
Logged In: YES
user_id=847188
Originator: NO
This is also a problem under HP-UX 11.0 with Python 2.5
The socket connect_ex() will return errno 22 EINVAL instead of
the more appropriate 239 ECONNREFUSED when connecting to a
non-listening socket ... but only if a socket timeout is being
used.
A system call trace reveils a little more what is going on.
For the python code
import socket
s = socket.socket( socket.AF_INET, socket.SOCK_STREAM )
s.settimeout(15.0)
res = s.connect_ex( ('127.0.0.1', 8099) ) # An unused port number
the system call sequence is as follows:
Calling socket.socket()
socket(AF_INET, SOCK_STREAM, 0) = 3
Calling s.settimeout(15.0)
fcntl(3, F_GETFL, 0) = 2
fcntl(3, F_SETFL, 65538) = 0
Calling s.connect_ex(...)
connect(3, 0x400b43f0, 16) = -1 -> ERR#245 EINPROGRESS
poll(0x7cff1914, 1, 15000) = 1
connect(3, 0x400b43f0, 16) = -1 -> ERR#22 EINVAL
If the call to settimeout is removed, then an ERR#239 ECONNREFUSED
is returned by the first connect() and no subsequent poll+connect
is attempted. With the timeout set, note that the poll() returns
immediately no timeout actually occurs.
Note that tracing the same code under Linux shows the exact same
set of system calls, but that the second connect() call returns
ECONNREFUSED instead.
So this appears to be a specific behavior of HP-UX (and
perhaps other Unixes).
Excerpted from the HP man pages for connect(2):
[EINVAL] The socket has already been shut down or
has a listen() active on it; addrlen is
a bad value; an attempt was made to
connect() an AF_UNIX socket to an NFS-
mounted (remote) name; the X.121 address
length is zero, negative, or greater
than 15 digits.
For datagram sockets, if addrlen is a
bad value, the peer address is no longer
maintained by the system.
[ECONNREFUSED] The attempt to connect was forcefully
rejected.
[EINPROGRESS] Nonblocking I/O is enabled using
O_NONBLOCK, O_NDELAY, or FIOSNBIO, and
the connection cannot be completed
immediately. This is not a failure.
Make the connect() call again a few
seconds later. Alternatively, wait for
completion by calling select() and
selecting for write.
----------------------------------------------------------------------
Comment By: Troels Walsted Hansen (troels)
Date: 2004-06-02 04:51
Message:
Logged In: YES
user_id=32863
The Windows part of this bug is a duplicate of bug #777597.
----------------------------------------------------------------------
You can respond by visiting:
https://sourceforge.net/tracker/?func=detail&atid=105470&aid=805194&group_id=5470
More information about the Python-bugs-list
mailing list