Issue 953599: asyncore misses socket closes when poll is used (original) (raw)

Issue953599

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:04 admin set github: 40253
2008-07-07 05:04:43 josiahcarlson set status: open -> closedresolution: fixedmessages: +
2008-01-04 04:10:28 christian.heimes set versions: + Python 2.6
2007-12-13 01:29:26 giampaolo.rodola set nosy: + giampaolo.rodola
2004-05-13 21:47:17 shane_kerr create