homepage

This issue tracker has been migrated to GitHub , and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

classification
Title: asyncore misses socket closes when poll is used
Type: Stage:
Components: Library (Lib) Versions: Python 2.6
process
Status: closed Resolution: fixed
Dependencies: Superseder:
Assigned To: josiahcarlson Nosy List: giampaolo.rodola, josiahcarlson, klimkin, shane_kerr
Priority: high Keywords:

Created on 2004年05月13日 21:47 by shane_kerr, last changed 2022年04月11日 14:56 by admin. This issue is now closed.

Files
File name Uploaded Description Edit
asyncore.py.diff shane_kerr, 2004年05月13日 21:47
Messages (4)
msg20798 - (view) Author: Shane Kerr (shane_kerr) Date: 2004年05月13日 21:47
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.
msg20799 - (view) Author: Alexey Klimkin (klimkin) Date: 2004年07月02日 13:56
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.
msg20800 - (view) Author: Josiah Carlson (josiahcarlson) * (Python triager) Date: 2007年01月06日 23:21
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()
msg69376 - (view) Author: Josiah Carlson (josiahcarlson) * (Python triager) Date: 2008年07月07日 05:04
Fixed for 2.6 in changelist 64768.
Fixed for 3.0 in changelist 64770.
History
Date User Action Args
2022年04月11日 14:56:04adminsetgithub: 40253
2008年07月07日 05:04:43josiahcarlsonsetstatus: open -> closed
resolution: fixed
messages: + msg69376
2008年01月04日 04:10:28christian.heimessetversions: + Python 2.6
2007年12月13日 01:29:26giampaolo.rodolasetnosy: + giampaolo.rodola
2004年05月13日 21:47:17shane_kerrcreate

AltStyle によって変換されたページ (->オリジナル) /