homepage

This issue tracker has been migrated to GitHub , and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

classification
Title: asyncore/Windows: select() doesn't report errors for a non-blocking connect()
Type: behavior Stage:
Components: asyncio, Library (Lib), Windows Versions: Python 2.3
process
Status: closed Resolution: fixed
Dependencies: Superseder: asyncore fixes and improvements
View: 909005
Assigned To: josiahcarlson Nosy List: ajaksu2, garth42, giampaolo.rodola, gvanrossum, intgr, johnjsmith, josiahcarlson, klimkin, vstinner, yselivanov
Priority: normal Keywords:

Created on 2003年07月25日 14:43 by garth42, last changed 2022年04月10日 16:10 by admin. This issue is now closed.

Messages (11)
msg17326 - (view) Author: Garth Bushell (garth42) Date: 2003年07月25日 14:43
asyncore.poll is broken on windows. If a connection is
refused happens it will hang for ever and never raise
an exception.
The Select statment never checks the exfds. This is
needed as this is where windows reports failed
connections. The documentation in the microsoft
platform SDK mentions this. 
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winsock/winsock/select_2.asp
The suggested fix is shown below althought this is
untested. The correct error number is recived from
getsockopt(SOL_SOCKET,SO_ERROR) 
def poll(timeout=0.0, map=None):
 if map is None:
 map = socket_map
 if map:
 r = []; w = []; e = []
 for fd, obj in map.items():
 if obj.readable():
 r.append(fd)
 if obj.writable():
 w.append(fd)
 if sys.platform == 'win32':
 if not obj.connected:
 e.append(fd)
 if [] == r == w == e:
 time.sleep(timeout)
 else:
 try:
 r, w, e = select.select(r, w, e, timeout)
 except select.error, err:
 if err[0] != EINTR:
 raise
 else:
 return
 if sys.platform == 'win32':
 for fd in e:
 obj = map.get(fd)
 if obj is None:
 continue
 errno =
fs.getsockopt(socket.SOL_SOCKET, socket.SO_ERROR)
 raise
socket.error,(errno,socketerrorTab[error])
 for fd in r:
 obj = map.get(fd)
 if obj is None:
 continue
 read(obj)
 for fd in w:
 obj = map.get(fd)
 if obj is None:
 continue
 write(obj)
msg17327 - (view) Author: John J Smith (johnjsmith) Date: 2003年07月29日 12:49
Logged In: YES 
user_id=830565
I was bitten by the same problem. My workaround (in a
Tkinter application) is given below.
Would it make sense to modify poll() to simply add the union
of r and w to e, and call handle_error() for any fd in e?
Workaround:
 try:
 self.connect(send_addr)
 except socket.error:
 self.handle_error()
 if sys.platform == 'win32':
 # Win98 select() doesn't seem to report errors for a
 # non-blocking connect().
 self.__connected = 0
 self.__frame.after(2000, self.__win_connect_poll)
...
 if sys.platform == 'win32':
 def __win_connect_poll (self):
 if self.__connected:
 return
 e = self.socket.getsockopt(socket.SOL_SOCKET,
 socket.SO_ERROR)
 if e in (0, errno.EINPROGRESS, 
errno.WSAEINPROGRESS):
 self.__frame.after(2000, self.__win_connect_poll)
 else:
 try:
 str = socket.errorTab[e]
 except KeyError:
 str = os.strerror(e)
 try:
 raise socket.error(e, str)
 except socket.error:
 self.handle_error()
msg17328 - (view) Author: Alexey Klimkin (klimkin) Date: 2004年03月04日 08:23
Logged In: YES 
user_id=410460
Patch #909005 fixes the problem.
msg17329 - (view) Author: Josiah Carlson (josiahcarlson) * (Python triager) Date: 2007年01月07日 06:19
I am looking into applying a variant of portions of #909005 to fix this bug.
msg81863 - (view) Author: Daniel Diniz (ajaksu2) * (Python triager) Date: 2009年02月13日 03:27
Looks like this one was solved in issue 909005, does anyone disagree?
msg81978 - (view) Author: Josiah Carlson (josiahcarlson) * (Python triager) Date: 2009年02月13日 23:46
According to Garth, sockets that don't connect on Windows get put into 
the error sockets list.
According to John, you need to poll sockets to determine whether or not 
the attempted connection was refused.
If Garth is right, the problem is fixed, though we aren't quite 
retrieving the correct error code on win32. If John is right, we need 
to repeatedly check for error conditions on sockets that are trying to 
connect to a remote host, and the problem is not fixed.
msg176687 - (view) Author: Marc Schlaich (schlamar) * Date: 2012年11月30日 14:08
This issue is not fixed. Another workaround would be the `win32select` function from twisted: http://twistedmatrix.com/trac/browser/trunk/twisted/internet/selectreactor.py#L23 
msg206573 - (view) Author: Mark Lawrence (BreamoreBoy) * Date: 2013年12月19日 03:15
Is it worth leaving this open given the arrival of the new asyncio module in Python 3.4?
msg219304 - (view) Author: STINNER Victor (vstinner) * (Python committer) Date: 2014年05月28日 21:44
This issue was opened 11 years ago, when Windows 95, 98, Me, 2000 and XP were used. Python is going to drop support of Windows XP, and most older versions are already no more supported. Does this issue still exist in recent Windows versions? I'm not aware of such bug.
Does asyncio have the bug?
msg221750 - (view) Author: STINNER Victor (vstinner) * (Python committer) Date: 2014年06月27日 22:40
"Workaround: (...)
e = self.socket.getsockopt(socket.SOL_SOCKET, socket.SO_ERROR)"
Oh, it looks like the issue was already fixed 4 years ago:
---
changeset: 63720:ba7353147507
branch: 3.1
parent: 63716:915b028b954d
user: Giampaolo Rodolà <g.rodola@gmail.com>
date: Wed Aug 04 09:04:53 2010 +0000
files: Lib/asyncore.py Misc/ACKS Misc/NEWS
description:
Merged revisions 83705 via svnmerge from
svn+ssh://pythondev@svn.python.org/python/branches/py3k
........
 r83705 | giampaolo.rodola | 2010年08月04日 11:02:27 +0200 (mer, 04 ago 2010) | 1 line
 fix issue #2944: asyncore doesn't handle connection refused correctly (patch by Alexander Shigin). Merged from 2.7 branch.
........
diff -r 915b028b954d -r ba7353147507 Lib/asyncore.py
--- a/Lib/asyncore.py Wed Aug 04 04:53:07 2010 +0000
+++ b/Lib/asyncore.py Wed Aug 04 09:04:53 2010 +0000
@@ -426,8 +426,11 @@ class dispatcher:
 self.handle_read()
 
 def handle_connect_event(self):
+ err = self.socket.getsockopt(socket.SOL_SOCKET, socket.SO_ERROR)
+ if err != 0:
+ raise socket.error(err, _strerror(err))
+ self.handle_connect()
 self.connected = True
- self.handle_connect()
 
 def handle_write_event(self):
 if self.accepting:
...
---
msg221751 - (view) Author: STINNER Victor (vstinner) * (Python committer) Date: 2014年06月27日 22:42
Note: asyncio also calls getsockopt(SOL_SOCKET,SO_ERROR) to check if the connect() succeeded or not, and so it doesn't have this bug.
History
Date User Action Args
2022年04月10日 16:10:12adminsetgithub: 38929
2014年06月27日 22:42:04vstinnersetmessages: + msg221751
2014年06月27日 22:40:49vstinnersetstatus: open -> closed
resolution: fixed
messages: + msg221750
2014年06月06日 11:52:29vstinnersettitle: asyncore is broken for windows if connection is refused -> asyncore/Windows: select() doesn't report errors for a non-blocking connect()
2014年06月06日 11:45:21vstinnersetnosy: + yselivanov, gvanrossum
components: + asyncio
2014年05月28日 21:44:33vstinnersetnosy: + vstinner
messages: + msg219304
2014年02月03日 15:41:32BreamoreBoysetnosy: - BreamoreBoy
2013年12月19日 19:37:41schlamarsetnosy: - schlamar
2013年12月19日 03:15:18BreamoreBoysetnosy: + BreamoreBoy
messages: + msg206573
2012年11月30日 14:08:28schlamarsetnosy: + schlamar
messages: + msg176687
2009年03月28日 12:18:28intgrsetnosy: + intgr
2009年02月13日 23:46:55josiahcarlsonsetmessages: + msg81978
2009年02月13日 03:27:42ajaksu2settype: behavior
superseder: asyncore fixes and improvements
messages: + msg81863
components: + Windows
nosy: + ajaksu2
2008年03月20日 00:55:45giampaolo.rodolasetnosy: + giampaolo.rodola
2003年07月25日 14:43:37garth42create

AltStyle によって変換されたページ (->オリジナル) /