Commit d0c5419e authored by Jeremy Hylton's avatar Jeremy Hylton

Merge in zeo-1_0-branch

Wrap send() and recv() calls in try/except

The try/except catches errors like EAGAIN that indicate transient
failures.  In those cases, treat as send() and recv() of no data and
return from method gracefully.
parent fd83f922
...@@ -85,11 +85,30 @@ ...@@ -85,11 +85,30 @@
"""Sized message async connections """Sized message async connections
""" """
__version__ = "$Revision: 1.10 $"[11:-2] __version__ = "$Revision: 1.11 $"[11:-2]
import asyncore, string, struct, zLOG, sys, Acquisition import asyncore, string, struct, zLOG, sys, Acquisition
import socket, errno
from zLOG import LOG, TRACE, ERROR, INFO from zLOG import LOG, TRACE, ERROR, INFO
# Use the dictionary to make sure we get the minimum number of errno
# entries. We expect that EWOULDBLOCK == EAGAIN on most systems --
# or that only one is actually used.
tmp_dict = {errno.EWOULDBLOCK: 0,
errno.EAGAIN: 0,
errno.EINTR: 0,
}
expected_socket_read_errors = tuple(tmp_dict.keys())
tmp_dict = {errno.EAGAIN: 0,
errno.EWOULDBLOCK: 0,
errno.ENOBUFS: 0,
errno.EINTR: 0,
}
expected_socket_write_errors = tuple(tmp_dict.keys())
del tmp_dict
class SizedMessageAsyncConnection(Acquisition.Explicit, asyncore.dispatcher): class SizedMessageAsyncConnection(Acquisition.Explicit, asyncore.dispatcher):
__append=None # Marker indicating that we're closed __append=None # Marker indicating that we're closed
...@@ -116,7 +135,12 @@ class SizedMessageAsyncConnection(Acquisition.Explicit, asyncore.dispatcher): ...@@ -116,7 +135,12 @@ class SizedMessageAsyncConnection(Acquisition.Explicit, asyncore.dispatcher):
join=string.join, StringType=type(''), _type=type, join=string.join, StringType=type(''), _type=type,
_None=None): _None=None):
d=self.recv(8096) try:
d=self.recv(8096)
except socket.error, err:
if err[0] in expected_socket_read_errors:
return
raise
if not d: return if not d: return
inp=self.__inp inp=self.__inp
...@@ -160,7 +184,12 @@ class SizedMessageAsyncConnection(Acquisition.Explicit, asyncore.dispatcher): ...@@ -160,7 +184,12 @@ class SizedMessageAsyncConnection(Acquisition.Explicit, asyncore.dispatcher):
output=self.__output output=self.__output
while output: while output:
v=output[0] v=output[0]
n=self.send(v) try:
n=self.send(v)
except socket.error, err:
if err[0] in expected_socket_write_errors:
break # we couldn't write anything
raise
if n < len(v): if n < len(v):
output[0]=v[n:] output[0]=v[n:]
break # we can't write any more break # we can't write any more
......
...@@ -85,11 +85,30 @@ ...@@ -85,11 +85,30 @@
"""Sized message async connections """Sized message async connections
""" """
__version__ = "$Revision: 1.10 $"[11:-2] __version__ = "$Revision: 1.11 $"[11:-2]
import asyncore, string, struct, zLOG, sys, Acquisition import asyncore, string, struct, zLOG, sys, Acquisition
import socket, errno
from zLOG import LOG, TRACE, ERROR, INFO from zLOG import LOG, TRACE, ERROR, INFO
# Use the dictionary to make sure we get the minimum number of errno
# entries. We expect that EWOULDBLOCK == EAGAIN on most systems --
# or that only one is actually used.
tmp_dict = {errno.EWOULDBLOCK: 0,
errno.EAGAIN: 0,
errno.EINTR: 0,
}
expected_socket_read_errors = tuple(tmp_dict.keys())
tmp_dict = {errno.EAGAIN: 0,
errno.EWOULDBLOCK: 0,
errno.ENOBUFS: 0,
errno.EINTR: 0,
}
expected_socket_write_errors = tuple(tmp_dict.keys())
del tmp_dict
class SizedMessageAsyncConnection(Acquisition.Explicit, asyncore.dispatcher): class SizedMessageAsyncConnection(Acquisition.Explicit, asyncore.dispatcher):
__append=None # Marker indicating that we're closed __append=None # Marker indicating that we're closed
...@@ -116,7 +135,12 @@ class SizedMessageAsyncConnection(Acquisition.Explicit, asyncore.dispatcher): ...@@ -116,7 +135,12 @@ class SizedMessageAsyncConnection(Acquisition.Explicit, asyncore.dispatcher):
join=string.join, StringType=type(''), _type=type, join=string.join, StringType=type(''), _type=type,
_None=None): _None=None):
d=self.recv(8096) try:
d=self.recv(8096)
except socket.error, err:
if err[0] in expected_socket_read_errors:
return
raise
if not d: return if not d: return
inp=self.__inp inp=self.__inp
...@@ -160,7 +184,12 @@ class SizedMessageAsyncConnection(Acquisition.Explicit, asyncore.dispatcher): ...@@ -160,7 +184,12 @@ class SizedMessageAsyncConnection(Acquisition.Explicit, asyncore.dispatcher):
output=self.__output output=self.__output
while output: while output:
v=output[0] v=output[0]
n=self.send(v) try:
n=self.send(v)
except socket.error, err:
if err[0] in expected_socket_write_errors:
break # we couldn't write anything
raise
if n < len(v): if n < len(v):
output[0]=v[n:] output[0]=v[n:]
break # we can't write any more break # we can't write any more
......
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