Commit 2ee08f1d authored by Denis Bilenko's avatar Denis Bilenko

socket: make wait_xxx() raise EBADF if waiting was cancelled

also use a message that is a bit different from standard in this case
parent e4a33ad7
...@@ -144,7 +144,7 @@ def wait_read(fileno, timeout=None, timeout_exc=timeout('timed out'), event=None ...@@ -144,7 +144,7 @@ def wait_read(fileno, timeout=None, timeout_exc=timeout('timed out'), event=None
If *timeout* is non-negative, then *timeout_exc* is raised after *timeout* second has passed. If *timeout* is non-negative, then *timeout_exc* is raised after *timeout* second has passed.
By default *timeout_exc* is ``socket.timeout('timed out')``. By default *timeout_exc* is ``socket.timeout('timed out')``.
Return ``True`` if the event was signalled normally, ``False`` if it was cancelled with :func:`cancel_wait`. If :func:`cancel_wait` is called, raise ``socket.error(EBADF, 'File descriptor was closed in another greenlet')``.
""" """
if event is None: if event is None:
event = core.read_event(fileno, _wait_helper, timeout, (getcurrent(), timeout_exc)) event = core.read_event(fileno, _wait_helper, timeout, (getcurrent(), timeout_exc))
...@@ -156,11 +156,9 @@ def wait_read(fileno, timeout=None, timeout_exc=timeout('timed out'), event=None ...@@ -156,11 +156,9 @@ def wait_read(fileno, timeout=None, timeout_exc=timeout('timed out'), event=None
try: try:
switch_result = get_hub().switch() switch_result = get_hub().switch()
assert event is switch_result, 'Invalid switch into wait_read(): %r' % (switch_result, ) assert event is switch_result, 'Invalid switch into wait_read(): %r' % (switch_result, )
cancelled = event.pending
finally: finally:
event.cancel() event.cancel()
event.arg = None event.arg = None
return not cancelled
def wait_write(fileno, timeout=None, timeout_exc=timeout('timed out'), event=None): def wait_write(fileno, timeout=None, timeout_exc=timeout('timed out'), event=None):
...@@ -169,7 +167,7 @@ def wait_write(fileno, timeout=None, timeout_exc=timeout('timed out'), event=Non ...@@ -169,7 +167,7 @@ def wait_write(fileno, timeout=None, timeout_exc=timeout('timed out'), event=Non
If *timeout* is non-negative, then *timeout_exc* is raised after *timeout* second has passed. If *timeout* is non-negative, then *timeout_exc* is raised after *timeout* second has passed.
By default *timeout_exc* is ``socket.timeout('timed out')``. By default *timeout_exc* is ``socket.timeout('timed out')``.
Return ``True`` if the event was signalled normally, ``False`` if it was cancelled with :func:`cancel_wait`. If :func:`cancel_wait` is called, raise ``socket.error(EBADF, 'File descriptor was closed in another greenlet')``.
""" """
if event is None: if event is None:
event = core.write_event(fileno, _wait_helper, timeout, (getcurrent(), timeout_exc)) event = core.write_event(fileno, _wait_helper, timeout, (getcurrent(), timeout_exc))
...@@ -181,11 +179,9 @@ def wait_write(fileno, timeout=None, timeout_exc=timeout('timed out'), event=Non ...@@ -181,11 +179,9 @@ def wait_write(fileno, timeout=None, timeout_exc=timeout('timed out'), event=Non
try: try:
switch_result = get_hub().switch() switch_result = get_hub().switch()
assert event is switch_result, 'Invalid switch into wait_write(): %r' % (switch_result, ) assert event is switch_result, 'Invalid switch into wait_write(): %r' % (switch_result, )
cancelled = event.pending
finally: finally:
event.arg = None event.arg = None
event.cancel() event.cancel()
return not cancelled
def wait_readwrite(fileno, timeout=None, timeout_exc=timeout('timed out'), event=None): def wait_readwrite(fileno, timeout=None, timeout_exc=timeout('timed out'), event=None):
...@@ -194,7 +190,7 @@ def wait_readwrite(fileno, timeout=None, timeout_exc=timeout('timed out'), event ...@@ -194,7 +190,7 @@ def wait_readwrite(fileno, timeout=None, timeout_exc=timeout('timed out'), event
If *timeout* is non-negative, then *timeout_exc* is raised after *timeout* second has passed. If *timeout* is non-negative, then *timeout_exc* is raised after *timeout* second has passed.
By default *timeout_exc* is ``socket.timeout('timed out')``. By default *timeout_exc* is ``socket.timeout('timed out')``.
Return ``True`` if the event was signalled normally, ``False`` if it was cancelled with :func:`cancel_wait`. If :func:`cancel_wait` is called, raise ``socket.error(EBADF, 'File descriptor was closed in another greenlet')``.
""" """
if event is None: if event is None:
event = core.readwrite_event(fileno, _wait_helper, timeout, (getcurrent(), timeout_exc)) event = core.readwrite_event(fileno, _wait_helper, timeout, (getcurrent(), timeout_exc))
...@@ -206,19 +202,16 @@ def wait_readwrite(fileno, timeout=None, timeout_exc=timeout('timed out'), event ...@@ -206,19 +202,16 @@ def wait_readwrite(fileno, timeout=None, timeout_exc=timeout('timed out'), event
try: try:
switch_result = get_hub().switch() switch_result = get_hub().switch()
assert event is switch_result, 'Invalid switch into wait_readwrite(): %r' % (switch_result, ) assert event is switch_result, 'Invalid switch into wait_readwrite(): %r' % (switch_result, )
cancelled = event.pending
finally: finally:
event.arg = None event.arg = None
event.cancel() event.cancel()
return not cancelled
def __cancel_wait(event): def __cancel_wait(event):
if event.pending: if event.pending:
arg = event.arg arg = event.arg
if arg is not None: if arg is not None:
greenlet, _ = arg arg[0].throw(error(errno.EBADF, 'File descriptor was closed in another greenlet'))
greenlet.switch(event)
def cancel_wait(event): def cancel_wait(event):
...@@ -328,8 +321,7 @@ class socket(object): ...@@ -328,8 +321,7 @@ class socket(object):
if ex[0] != errno.EWOULDBLOCK or self.timeout == 0.0: if ex[0] != errno.EWOULDBLOCK or self.timeout == 0.0:
raise raise
sys.exc_clear() sys.exc_clear()
if not wait_read(sock.fileno(), timeout=self.timeout, event=self._read_event): wait_read(sock.fileno(), timeout=self.timeout, event=self._read_event)
raise error(errno.EBADF, 'Bad file descriptor')
return socket(_sock=client_socket), address return socket(_sock=client_socket), address
def close(self): def close(self):
...@@ -356,8 +348,7 @@ class socket(object): ...@@ -356,8 +348,7 @@ class socket(object):
if not result or result == EISCONN: if not result or result == EISCONN:
break break
elif (result in (EWOULDBLOCK, EINPROGRESS, EALREADY)) or (result == EINVAL and is_windows): elif (result in (EWOULDBLOCK, EINPROGRESS, EALREADY)) or (result == EINVAL and is_windows):
if not wait_readwrite(sock.fileno(), event=self._rw_event): wait_readwrite(sock.fileno(), event=self._rw_event)
raise error(errno.EBADF, 'Bad file descriptor')
else: else:
raise error(result, strerror(result)) raise error(result, strerror(result))
else: else:
...@@ -373,8 +364,7 @@ class socket(object): ...@@ -373,8 +364,7 @@ class socket(object):
timeleft = end - time.time() timeleft = end - time.time()
if timeleft <= 0: if timeleft <= 0:
raise timeout('timed out') raise timeout('timed out')
if not wait_readwrite(sock.fileno(), timeout=timeleft, event=self._rw_event): wait_readwrite(sock.fileno(), timeout=timeleft, event=self._rw_event)
raise error(errno.EBADF, 'Bad file descriptor')
else: else:
raise error(result, strerror(result)) raise error(result, strerror(result))
...@@ -413,8 +403,12 @@ class socket(object): ...@@ -413,8 +403,12 @@ class socket(object):
raise raise
# QQQ without clearing exc_info test__refcount.test_clean_exit fails # QQQ without clearing exc_info test__refcount.test_clean_exit fails
sys.exc_clear() sys.exc_clear()
if not wait_read(sock.fileno(), timeout=self.timeout, event=self._read_event): try:
return '' wait_read(sock.fileno(), timeout=self.timeout, event=self._read_event)
except error, ex:
if ex[0] == errno.EBADF:
return ''
raise
def recvfrom(self, *args): def recvfrom(self, *args):
sock = self._sock sock = self._sock
...@@ -425,8 +419,7 @@ class socket(object): ...@@ -425,8 +419,7 @@ class socket(object):
if ex[0] != EWOULDBLOCK or self.timeout == 0.0: if ex[0] != EWOULDBLOCK or self.timeout == 0.0:
raise raise
sys.exc_clear() sys.exc_clear()
if not wait_read(sock.fileno(), timeout=self.timeout, event=self._read_event): wait_read(sock.fileno(), timeout=self.timeout, event=self._read_event)
raise error(errno.EBADF, 'Bad file descriptor')
def recvfrom_into(self, *args): def recvfrom_into(self, *args):
sock = self._sock sock = self._sock
...@@ -437,8 +430,7 @@ class socket(object): ...@@ -437,8 +430,7 @@ class socket(object):
if ex[0] != EWOULDBLOCK or self.timeout == 0.0: if ex[0] != EWOULDBLOCK or self.timeout == 0.0:
raise raise
sys.exc_clear() sys.exc_clear()
if not wait_read(sock.fileno(), timeout=self.timeout, event=self._read_event): wait_read(sock.fileno(), timeout=self.timeout, event=self._read_event)
raise error(errno.EBADF, 'Bad file descriptor')
def recv_into(self, *args): def recv_into(self, *args):
sock = self._sock sock = self._sock
...@@ -451,8 +443,12 @@ class socket(object): ...@@ -451,8 +443,12 @@ class socket(object):
if ex[0] != EWOULDBLOCK or self.timeout == 0.0: if ex[0] != EWOULDBLOCK or self.timeout == 0.0:
raise raise
sys.exc_clear() sys.exc_clear()
if not wait_read(sock.fileno(), timeout=self.timeout, event=self._read_event): try:
return 0 wait_read(sock.fileno(), timeout=self.timeout, event=self._read_event)
except error, ex:
if ex[0] == errno.EBADF:
return 0
raise
def send(self, data, flags=0, timeout=timeout_default): def send(self, data, flags=0, timeout=timeout_default):
sock = self._sock sock = self._sock
...@@ -464,8 +460,12 @@ class socket(object): ...@@ -464,8 +460,12 @@ class socket(object):
if ex[0] != EWOULDBLOCK or timeout == 0.0: if ex[0] != EWOULDBLOCK or timeout == 0.0:
raise raise
sys.exc_clear() sys.exc_clear()
if not wait_write(sock.fileno(), timeout=timeout, event=self._write_event): try:
return 0 wait_write(sock.fileno(), timeout=timeout, event=self._write_event)
except error, ex:
if ex[0] == errno.EBADF:
return 0
raise
try: try:
return sock.send(data, flags) return sock.send(data, flags)
except error, ex2: except error, ex2:
...@@ -502,8 +502,7 @@ class socket(object): ...@@ -502,8 +502,7 @@ class socket(object):
if ex[0] != EWOULDBLOCK or timeout == 0.0: if ex[0] != EWOULDBLOCK or timeout == 0.0:
raise raise
sys.exc_clear() sys.exc_clear()
if not wait_write(sock.fileno(), timeout=self.timeout, event=self._write_event): wait_write(sock.fileno(), timeout=self.timeout, event=self._write_event)
raise error(errno.EBADF, 'Bad file descriptor')
try: try:
return sock.sendto(*args) return sock.sendto(*args)
except error, ex2: except error, ex2:
......
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