Bugs item #953599, was opened at 2004-05-13 14:47
Message generated for change (Comment added) made by josiahcarlson
You can respond by visiting:
https://sourceforge.net/tracker/?func=detail&atid=105470&aid=953599&group_id=5470
Please note that this message will contain a full copy of the comment thread,
including the initial issue submission, for this request,
not just the latest update.
Category: Python Library
Group: None
Status: Open
Resolution: None
Priority: 6
Private: No
Submitted By: Shane Kerr (shane_kerr)
Assigned to: Josiah Carlson (josiahcarlson)
Summary: asyncore misses socket closes when poll is used
Initial Comment:
Problem:
If the loop() function of asyncore is invoked with poll
rather than select, the function readwrite() is used
when I/O is available on a socket. However, this
function does not check for hangup - provided by POLLHUP.
If a socket is attempting to write, then POLLOUT never
gets set, so the socket hangs.
Because poll() is returning immediately, but the return
value is never used, asyncore busy-loops, consuming all
available CPU.
Possible solutions:
The easy solution is to check for POLLHUP in the
readwrite() function:
if flags & (select.POLLOUT | select.POLLHUP):
obj.handle_write_event()
This makes the poll work exactly like the select - the
application raises a socket.error set to EPIPE.
An alternate solution - possibly more graceful - is to
invoke the handle_close() method of the object:
if flags & select.POLLHUP:
obj.handle_close()
else:
if flags & select.POLLIN:
obj.handle_read_event()
if flags & select.pollout:
obj.handle_write_event()
This is incompatible with the select model, but it
means that the read and write logic is now the same for
socket hangups - handle_close() is invoked.
----------------------------------------------------------------------
>Comment By: Josiah Carlson (josiahcarlson)
Date: 2007-01-06 15:21
Message:
Logged In: YES
user_id=341410
Originator: NO
The solution suggested by klimkin seems to have made it into revision
35513 as a fix to bug #887279.
I'm not sure that this is necessarily the right solution to this bug or
#887279, as a socket disconnect isn't necessarily an error condition,
otherwise .handle_close_event() shouldn't exist for select-based loops,
and it should always be an error.
Suggest switching to the last if clause of readwrite() to...
if flags & (select.POLLERR | select.POLLNVAL):
obj.handle_expt_event()
if flags & select.POLLHUP:
obj.handle_close_event()
----------------------------------------------------------------------
Comment By: Alexey Klimkin (klimkin)
Date: 2004-07-02 06:56
Message:
Logged In: YES
user_id=410460
Perhaps, it would be better to raise exception:
def readwrite(obj, flags):
try:
if flags & (select.POLLIN | select.POLLPRI):
obj.handle_read_event()
if flags & select.POLLOUT:
obj.handle_write_event()
if flags & (select.POLLERR | select.POLLHUP |
select.POLLNVAL):
obj.handle_expt_event()
except ExitNow:
raise
except:
obj.handle_error()
...
def handle_expt_event(self):
err = self.socket.getsockopt(socket.SOL_SOCKET,
socket.SO_ERROR)
assert(err != 0)
raise socket.error, (err, errorcode[err])
Since asyncore closes socket in handle_error, this solves
the problem too.
----------------------------------------------------------------------
You can respond by visiting:
https://sourceforge.net/tracker/?func=detail&atid=105470&aid=953599&group_id=5470
_______________________________________________
Python-bugs-list mailing list
Unsubscribe:
http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com