Commit 1e80a425 authored by Denis Bilenko's avatar Denis Bilenko

socket: fix issue #26. store events used by reader and writer on the socket object.

It's no longer possible to read or write from more than one greenlet. An AssertionError would be raised in the second greenlet if you do. (It's still OK to recv in one greenlet and send in another).
parent 380a63e0
...@@ -266,6 +266,8 @@ class socket(object): ...@@ -266,6 +266,8 @@ class socket(object):
self._sock = _sock self._sock = _sock
self.timeout = _socket.getdefaulttimeout() self.timeout = _socket.getdefaulttimeout()
self._sock.setblocking(0) self._sock.setblocking(0)
self._read_event = core.event(core.EV_READ, self.fileno(), _wait_helper)
self._write_event = core.event(core.EV_WRITE, self.fileno(), _wait_helper)
def __repr__(self): def __repr__(self):
return '<%s at %s %s>' % (type(self).__name__, hex(id(self)), self._formatinfo()) return '<%s at %s %s>' % (type(self).__name__, hex(id(self)), self._formatinfo())
...@@ -306,10 +308,14 @@ class socket(object): ...@@ -306,10 +308,14 @@ 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()
wait_read(self._sock.fileno(), timeout=self.timeout) wait_read(self._sock.fileno(), timeout=self.timeout, event=self._read_event)
return socket(_sock=client_socket), address return socket(_sock=client_socket), address
def close(self): def close(self):
if self._read_event is not None:
cancel_wait(self._read_event)
if self._write_event is not None:
cancel_wait(self._write_event)
self._sock = _closedsocket() self._sock = _closedsocket()
dummy = self._sock._dummy dummy = self._sock._dummy
for method in _delegate_methods: for method in _delegate_methods:
...@@ -380,11 +386,13 @@ class socket(object): ...@@ -380,11 +386,13 @@ class socket(object):
#print 'received: %r' % (res, ) #print 'received: %r' % (res, )
return res return res
except error, ex: except error, ex:
if ex[0] == errno.EBADF:
return ''
if ex[0] != EWOULDBLOCK or self.timeout == 0.0: if ex[0] != EWOULDBLOCK or self.timeout == 0.0:
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()
wait_read(self.fileno(), timeout=self.timeout) wait_read(self.fileno(), timeout=self.timeout, event=self._read_event)
def recvfrom(self, *args): def recvfrom(self, *args):
while True: while True:
...@@ -394,7 +402,7 @@ class socket(object): ...@@ -394,7 +402,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()
wait_read(self._sock.fileno(), timeout=self.timeout) wait_read(self._sock.fileno(), timeout=self.timeout, event=self._read_event)
def recvfrom_into(self, *args): def recvfrom_into(self, *args):
while True: while True:
...@@ -404,17 +412,19 @@ class socket(object): ...@@ -404,17 +412,19 @@ 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()
wait_read(self._sock.fileno(), timeout=self.timeout) wait_read(self._sock.fileno(), timeout=self.timeout, event=self._read_event)
def recv_into(self, *args): def recv_into(self, *args):
while True: while True:
try: try:
return self._sock.recv_into(*args) return self._sock.recv_into(*args)
except error, ex: except error, ex:
if ex[0] == errno.EBADF:
return 0
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()
wait_read(self._sock.fileno(), timeout=self.timeout) wait_read(self._sock.fileno(), timeout=self.timeout, event=self._read_event)
def send(self, data, flags=0, timeout=timeout_default): def send(self, data, flags=0, timeout=timeout_default):
#print 'sending: %r' % data #print 'sending: %r' % data
...@@ -426,7 +436,7 @@ class socket(object): ...@@ -426,7 +436,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()
wait_write(self._sock.fileno(), timeout=timeout) wait_write(self._sock.fileno(), timeout=timeout, event=self._write_event)
try: try:
return self._sock.send(data, flags) return self._sock.send(data, flags)
except error, ex2: except error, ex2:
...@@ -462,7 +472,7 @@ class socket(object): ...@@ -462,7 +472,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()
wait_write(self.fileno(), timeout=self.timeout) wait_write(self.fileno(), timeout=self.timeout, event=self._write_event)
try: try:
return self._sock.sendto(*args) return self._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