EINTR ... was Re: [Zope-dev] browser closing connection
Matthew T. Kromer
matt@zope.com
Mon, 10 Dec 2001 18:11:14 -0500
This is a multi-part message in MIME format.
--------------040300040001020308050803
Content-Type: text/plain; charset=us-ascii; format=flowed
Content-Transfer-Encoding: 7bit
>
>
>>>Also, for the record we usually get a bunch of these quite often:
>>>
>>>2001-11-04T09:04:33 ERROR(200) ZServer uncaptured
>>> python exception, closing channel <zhttp_channel connected
>>> XXX.XXX.XXX.XXX:2181 at fb4edc channel#: 2286 requests:4>
>>> (socket.error:(32, 'Broken pipe')
>>>
>>>[/usr/local/zope/dist/Zope-2.4.1/ZServer/medusa/asynchat.py|initiate_send|21
>>>4] [/usr/local/zope/dist/Zope-2.4.1/ZServer/medusa/http_server.py|send|414]
>>>[/usr/local/zope/sw/Python2.1.1/lib/python2.1/asyncore.py|send|330])
>>>
>>>
>>>We were seeing the same error (asyncore.py|send|330, etc) on solaris.
>>>
>>>
>
>
For what its worth, I tracked this down in the sources and confirmed
that in Zope 2.3, we shipped a modified asyncore.py with Medusa that
handled EINTR, but in Zope 2.4 we used stock Python's asyncore which
does NOT handle EINTR being returned from select(). IMHO, the
distributed Python 2.1 asyncore behavior is incorrect.
I've attached a diff of a portion of the differences (manually edited to
take out other patches).
I suspect this patch never got integrated due to ugliness of "while 1"
Also, the "what should this be" comment relates to NT's error numbers.
Visual C++ has an errno.h that lists EINTR as 4 -- And winsock.h
defines WSAEINTR as 10004 (ie add 10,000 to the errno). SO that number
should be 10004, not 0 for correctness on Windows.
--------------040300040001020308050803
Content-Type: text/plain;
name="eintr.diff"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
filename="eintr.diff"
--- /usr/local/python-2.1.1/lib/python2.1/asyncore.py Fri Nov 9 16:28:15 2001
+++ asyncore.py Sun Oct 1 11:58:56 2000
@@ -59,8 +39,10 @@
ECONNRESET = 10054
ENOTCONN = 10057
ESHUTDOWN = 10058
+ EINTR = 0 # what should this be?
else:
- from errno import EALREADY, EINPROGRESS, EWOULDBLOCK, ECONNRESET, ENOTCONN, ESHUTDOWN
+ from errno import EALREADY, EINPROGRESS, EWOULDBLOCK, ECONNRESET
+ from errno import ENOTCONN, ESHUTDOWN, EINTR
try:
socket_map
@@ -83,7 +65,13 @@
r.append (fd)
if obj.writable():
w.append (fd)
- r,w,e = select.select (r,w,e, timeout)
+
+ while 1:
+ try: r,w,e = select.select (r,w,e, timeout)
+ except select.error, v:
+ if v[0] != EINTR: raise
+ else: break
+
if DEBUG:
print r,w,e
--------------040300040001020308050803--