Commit 350c94b9 authored by Giampaolo Rodola's avatar Giampaolo Rodola

fix #10340: properly handle EINVAL on OSX and also avoid to call...

fix #10340: properly handle EINVAL on OSX and also avoid to call handle_connect() in case of a disconnetected socket which is not meant to connect.
parent 9faf5ee7
...@@ -225,6 +225,7 @@ class dispatcher: ...@@ -225,6 +225,7 @@ class dispatcher:
debug = False debug = False
connected = False connected = False
accepting = False accepting = False
connecting = False
closing = False closing = False
addr = None addr = None
ignore_log_types = frozenset(['warning']) ignore_log_types = frozenset(['warning'])
...@@ -248,7 +249,7 @@ class dispatcher: ...@@ -248,7 +249,7 @@ class dispatcher:
try: try:
self.addr = sock.getpeername() self.addr = sock.getpeername()
except socket.error as err: except socket.error as err:
if err.args[0] == ENOTCONN: if err.args[0] in (ENOTCONN, EINVAL):
# To handle the case where we got an unconnected # To handle the case where we got an unconnected
# socket. # socket.
self.connected = False self.connected = False
...@@ -342,6 +343,7 @@ class dispatcher: ...@@ -342,6 +343,7 @@ class dispatcher:
def connect(self, address): def connect(self, address):
self.connected = False self.connected = False
self.connecting = True
err = self.socket.connect_ex(address) err = self.socket.connect_ex(address)
if err in (EINPROGRESS, EALREADY, EWOULDBLOCK) \ if err in (EINPROGRESS, EALREADY, EWOULDBLOCK) \
or err == EINVAL and os.name in ('nt', 'ce'): or err == EINVAL and os.name in ('nt', 'ce'):
...@@ -401,6 +403,7 @@ class dispatcher: ...@@ -401,6 +403,7 @@ class dispatcher:
def close(self): def close(self):
self.connected = False self.connected = False
self.accepting = False self.accepting = False
self.connecting = False
self.del_channel() self.del_channel()
try: try:
self.socket.close() self.socket.close()
...@@ -439,6 +442,7 @@ class dispatcher: ...@@ -439,6 +442,7 @@ class dispatcher:
# sockets that are connected # sockets that are connected
self.handle_accept() self.handle_accept()
elif not self.connected: elif not self.connected:
if self.connecting:
self.handle_connect_event() self.handle_connect_event()
self.handle_read() self.handle_read()
else: else:
...@@ -450,6 +454,7 @@ class dispatcher: ...@@ -450,6 +454,7 @@ class dispatcher:
raise socket.error(err, _strerror(err)) raise socket.error(err, _strerror(err))
self.handle_connect() self.handle_connect()
self.connected = True self.connected = True
self.connecting = False
def handle_write_event(self): def handle_write_event(self):
if self.accepting: if self.accepting:
...@@ -458,11 +463,7 @@ class dispatcher: ...@@ -458,11 +463,7 @@ class dispatcher:
return return
if not self.connected: if not self.connected:
#check for errors if self.connecting:
err = self.socket.getsockopt(socket.SOL_SOCKET, socket.SO_ERROR)
if err != 0:
raise socket.error(err, _strerror(err))
self.handle_connect_event() self.handle_connect_event()
self.handle_write() self.handle_write()
......
...@@ -7,6 +7,7 @@ import sys ...@@ -7,6 +7,7 @@ import sys
import time import time
import warnings import warnings
import errno import errno
import struct
from test import support from test import support
from test.support import TESTFN, run_unittest, unlink from test.support import TESTFN, run_unittest, unlink
...@@ -730,6 +731,21 @@ class BaseTestAPI(unittest.TestCase): ...@@ -730,6 +731,21 @@ class BaseTestAPI(unittest.TestCase):
finally: finally:
sock.close() sock.close()
@unittest.skipUnless(threading, 'Threading required for this test.')
@support.reap_threads
def test_quick_connect(self):
# see: http://bugs.python.org/issue10340
server = TCPServer()
t = threading.Thread(target=lambda: asyncore.loop(timeout=0.1, count=500))
t.start()
for x in range(20):
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_LINGER,
struct.pack('ii', 1, 0))
s.connect(server.address)
s.close()
class TestAPI_UseSelect(BaseTestAPI): class TestAPI_UseSelect(BaseTestAPI):
use_poll = False use_poll = False
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment