Skip to content

Commit 9e5b778

Browse files
committed
Fixing bug with raise without exception
1 parent f502b13 commit 9e5b778

File tree

2 files changed

+28
-8
lines changed

2 files changed

+28
-8
lines changed

src/tarantool/connection.py

Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -77,10 +77,11 @@ def __init__(self, host, port,
7777
else:
7878
self.schema = Schema(schema)
7979
self._socket = None
80+
self.connected = False
8081
if connect_now:
8182
self.connect()
8283
self._libc = ctypes.CDLL(ctypes.util.find_library('c'), use_errno=True)
83-
self._recv_type = ctypes.CFUNCTYPE(ctypes.c_ssize_t, *[ctypes.c_int, ctypes.c_void_p, ctypes.c_ssize_t, ctypes.c_int], use_errno=True)
84+
self._recv_type = ctypes.CFUNCTYPE(ctypes.c_ssize_t, ctypes.c_int, ctypes.c_void_p, ctypes.c_ssize_t, ctypes.c_int, use_errno=True)
8485
self._recv = self._recv_type(self._libc.recv)
8586

8687
def close(self):
@@ -101,6 +102,7 @@ def connect(self):
101102

102103
try:
103104
# If old socket already exists - close it and re-create
105+
self.connected = True
104106
if self._socket:
105107
self._socket.close()
106108
self._socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
@@ -110,6 +112,7 @@ def connect(self):
110112
# Otherwise the timeout exception will rised, even if the server does not listen
111113
self._socket.settimeout(self.socket_timeout)
112114
except socket.error as e:
115+
self.connected = False
113116
raise NetworkError(e)
114117

115118
def _read_response(self):
@@ -157,19 +160,33 @@ def _send_request_wo_reconnect(self, request, space_name = None, field_defs = No
157160
raise DatabaseError(response.return_code, response.return_message)
158161

159162
def _opt_reconnect(self):
163+
'''\
164+
Check that connection is alive using low-level recv from libc(ctypes)
165+
**Due to bug in python - timeout is internal python construction.
166+
'''
167+
def check(): # Check that connection is alive
168+
rc = self._recv(self._socket.fileno(), '', 0, socket.MSG_DONTWAIT)
169+
if ctypes.get_errno() == errno.EAGAIN:
170+
ctypes.set_errno(0)
171+
return errno.EAGAIN
172+
return ctypes.get_errno()
173+
160174
attempt = 0
175+
last_errno = 0
161176
if not self._socket:
162177
self.connect()
163178
while True:
164-
rc = self._recv(self._socket.fileno(), '', 0, socket.MSG_DONTWAIT)
165-
if ctypes.get_errno() == errno.EAGAIN:
166-
ctypes.set_errno(0)
179+
last_errno = check()
180+
if self.connected and last_errno == errno.EAGAIN:
167181
break
168182
time.sleep(self.reconnect_delay)
169-
self.connect()
183+
try:
184+
self.connect()
185+
except NetworkError as e:
186+
last_errno = e.errno
170187
warn("Reconnect attempt %d of %d"%(attempt, self.reconnect_max_attempts), NetworkWarning)
171188
if attempt == self.reconnect_max_attempts:
172-
raise
189+
raise socket.error((last_errno, errno.errorcode[last_errno]))
173190
attempt += 1
174191

175192
def _send_request(self, request, space_name = None, field_defs = None, default_type = None):
@@ -247,7 +264,7 @@ def replace(self, space_name, values, return_tuple=None):
247264
:type values: tuple
248265
:param return_tuple: True indicates that it is required to return the inserted tuple back
249266
:type return_tuple: bool
250-
267+
251268
:rtype: `Response` instance
252269
'''
253270
if return_tuple is None:
@@ -399,7 +416,7 @@ def select(self, space_name, values=None, **kwargs):
399416
:type limit: int
400417
401418
:rtype: `Response` instance
402-
419+
403420
Select one single record (from space=0 and using index=0)
404421
>>> select(0, 0, 1)
405422

src/tarantool/error.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,9 @@ def os_strerror_patched(code):
106106
class NetworkError(DatabaseError):
107107
'''Error related to network'''
108108
def __init__(self, orig_exception=None, *args):
109+
self.errno = 0;
110+
if hasattr(orig_exception, 'errno'):
111+
self.errno = orig_exception.errno
109112
if orig_exception:
110113
if isinstance(orig_exception, socket.timeout):
111114
self.message = "Socket timeout"

0 commit comments

Comments
 (0)