Skip to content

Commit e7aac2e

Browse files
committed
Handle system interrupts during socket.create_connection
This is in a similar vein to #250, but the root cause of this issue is actually an upstream python issue (http://bugs.python.org/issue20611) which is not fixed in 2.x or <3.5. Python doesn't handle interrupted system calls-- so the applications are responsible for doing so. This patch simply retries the create_connection call on system call interrupt, while honoring the original timeout request. Note: although the timeout for `create_tcp_connection` will be honored, if there are interrupts each subsequent call to `create_connection` will have less time to complete.
1 parent dd5281f commit e7aac2e

2 files changed

Lines changed: 26 additions & 4 deletions

File tree

kazoo/handlers/threading.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -147,8 +147,8 @@ def select(self, *args, **kwargs):
147147
timeout = args[3] if len(args) == 4 else None
148148
# either the time to give up, or None
149149
end = (time.time() + timeout) if timeout else None
150-
while timeout is None or time.time() < end:
151-
if timeout:
150+
while end is None or time.time() < end:
151+
if end is not None:
152152
args = list(args) # make a list, since tuples aren't mutable
153153
args[3] = end - time.time() # set the timeout to the remaining time
154154
try:
@@ -161,6 +161,8 @@ def select(self, *args, **kwargs):
161161
if errnum == errno.EINTR:
162162
continue
163163
raise
164+
# if we hit our timeout, lets return as a timeout
165+
return ([], [], [])
164166

165167
def socket(self):
166168
return utils.create_tcp_socket(socket)

kazoo/handlers/utils.py

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import errno
44
import functools
55
import select
6+
import time
67

78
HAS_FNCTL = True
89
try:
@@ -182,12 +183,31 @@ def create_tcp_socket(module):
182183

183184

184185
def create_tcp_connection(module, address, timeout=None):
186+
end = None
185187
if timeout is None:
186188
# thanks to create_connection() developers for
187189
# this ugliness...
188-
timeout = module._GLOBAL_DEFAULT_TIMEOUT
190+
timeout = module.getdefaulttimeout()
191+
if timeout is not None:
192+
end = time.time() + timeout
193+
sock = None
194+
195+
while end is None or time.time() < end:
196+
try:
197+
# if we got a timeout, lets ensure that we decrement the time
198+
# otherwise there is no timeout set and we'll call it as such
199+
timeout_at = end if end is None else end - time.time()
200+
sock = module.create_connection(address, timeout_at)
201+
break
202+
except Exception as ex:
203+
errnum = ex.errno if isinstance(ex, OSError) else ex[0]
204+
if errnum == errno.EINTR:
205+
continue
206+
raise
207+
208+
if sock is None:
209+
raise module.error
189210

190-
sock = module.create_connection(address, timeout)
191211
_set_default_tcpsock_options(module, sock)
192212
return sock
193213

0 commit comments

Comments
 (0)