Skip to content

Commit 1b4bca7

Browse files
committed
Merge pull request #395 from jacksontj/system_call_interrupts
System call interrupts
2 parents 870a0ef + e7aac2e commit 1b4bca7

2 files changed

Lines changed: 42 additions & 13 deletions

File tree

kazoo/handlers/threading.py

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -143,17 +143,26 @@ def stop(self):
143143
python2atexit.unregister(self.stop)
144144

145145
def select(self, *args, **kwargs):
146-
try:
147-
return select.select(*args, **kwargs)
148-
except select.error as ex:
149-
# if the system call was interrupted, we'll return as a timeout
150-
# in Python 3, system call interruptions are a native exception
151-
# in Python 2, they are not
152-
errnum = ex.errno if isinstance(ex, OSError) else ex[0]
153-
# to mimic a timeout, we return the same thing select would
154-
if errnum == errno.EINTR:
155-
return ([], [], [])
156-
raise
146+
# select() takes no kwargs, so it will be in args
147+
timeout = args[3] if len(args) == 4 else None
148+
# either the time to give up, or None
149+
end = (time.time() + timeout) if timeout else None
150+
while end is None or time.time() < end:
151+
if end is not None:
152+
args = list(args) # make a list, since tuples aren't mutable
153+
args[3] = end - time.time() # set the timeout to the remaining time
154+
try:
155+
return select.select(*args, **kwargs)
156+
except select.error as ex:
157+
# if the system call was interrupted, we'll retry until timeout
158+
# in Python 3, system call interruptions are a native exception
159+
# in Python 2, they are not
160+
errnum = ex.errno if isinstance(ex, OSError) else ex[0]
161+
if errnum == errno.EINTR:
162+
continue
163+
raise
164+
# if we hit our timeout, lets return as a timeout
165+
return ([], [], [])
157166

158167
def socket(self):
159168
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)