Created
November 13, 2015 22:10
-
-
Save jimbaker/72a44fd7c54d26bcc4b0 to your computer and use it in GitHub Desktop.
Diff for socket.connect_ex to returning EALREADY when a socket connection is already in progress
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff -r 03f797ecd7ea Lib/_socket.py | |
--- a/Lib/_socket.py Thu Nov 12 13:47:41 2015 +1100 | |
+++ b/Lib/_socket.py Fri Nov 13 15:08:47 2015 -0700 | |
@@ -28,7 +28,8 @@ | |
from java.util import NoSuchElementException | |
from java.util.concurrent import ( | |
ArrayBlockingQueue, CopyOnWriteArrayList, CountDownLatch, LinkedBlockingQueue, | |
- RejectedExecutionException, ThreadFactory, TimeUnit) | |
+ ExecutionException, RejectedExecutionException, ThreadFactory, | |
+ TimeoutException, TimeUnit) | |
from java.util.concurrent.atomic import AtomicBoolean, AtomicLong | |
from javax.net.ssl import SSLPeerUnverifiedException, SSLException | |
@@ -852,7 +853,7 @@ | |
if self.bind_addr: | |
log.debug("Connect %s to %s", self.bind_addr, addr, extra={"sock": self}) | |
- bind_future = bootstrap.bind(self.bind_addr) | |
+ bind_future = bootstrap.bind(self.bind_addr).sync() | |
self._handle_channel_future(bind_future, "local bind") | |
self.channel = bind_future.channel() | |
else: | |
@@ -888,16 +889,39 @@ | |
log.debug("Completed connection to %s", addr, extra={"sock": self}) | |
def connect_ex(self, addr): | |
+ was_connecting = self.connected # actually means self.connecting if | |
+ # not blocking | |
if not self.connected: | |
try: | |
self.connect(addr) | |
except error as e: | |
return e.errno | |
if not self.connect_future.isDone(): | |
- return errno.EINPROGRESS | |
+ if was_connecting: | |
+ try: | |
+ # Timing is based on CPython and was empirically | |
+ # guestimated. Of course this means user code is | |
+ # polling, so the the best we can do is wait like | |
+ # this in supposedly nonblocking mode without | |
+ # completely busy waiting! | |
+ self.connect_future.get(1500, TimeUnit.MICROSECONDS) | |
+ except ExecutionException: | |
+ # generally raised if closed; pick up the state | |
+ # when testing for success | |
+ pass | |
+ except TimeoutException: | |
+ # more than 1.5ms, will report EALREADY below | |
+ pass | |
+ | |
+ if not self.connect_future.isDone(): | |
+ if was_connecting: | |
+ return errno.EALREADY | |
+ else: | |
+ return errno.EINPROGRESS | |
elif self.connect_future.isSuccess(): | |
return errno.EISCONN | |
else: | |
+ print self.connect_future.cause() | |
return errno.ENOTCONN | |
# SERVER METHODS |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment