Nir Soffer added the comment: Adding more info after discussion in github.
After polling readable/writeable dispatchers, asyncore.poll(2) receive a list of ready file descriptors, and invoke callbacks on the dispatcher objects. If a dispatchers is closed and and a new dispatcher is created, the new dispatcher may get the same file descriptor. If the file descriptor was in the ready list returned from poll()/select(), asyncore may try to invoke one of the callbacks (e.g. handle_write) on the new dispatcher. Here is an example in asycore.poll() r, w, e = select.select(r, w, e, timeout) for fd in r: obj = map.get(fd) if obj is None: continue read(obj) read close obj, removing fd from map, then creates a new one getting the same fd... for fd in w: obj = map.get(fd) this get the new object from the map, instead of the closed one. if obj is None: continue write(obj) invoke write on the wrong socket, which is not writable for fd in e: obj = map.get(fd) same issue here if obj is None: continue _exception(obj) asyncore.poll2() has same issue: r = pollster.poll(timeout) for fd, flags in r: obj = map.get(fd) if obj is None: continue readwrite(obj, flags) fd may have been closed and recreated by in a previous iteration of the loop. This issue is demonstrated in the failing test: https://github.com/python/cpython/pull/2707/commits/5aeb0098d2347984f3a89cf036c305edd2b8382b ---------- title: Race condition in asyncore wrongly closes channel -> Race condition in asyncore may access the wrong dispatcher _______________________________________ Python tracker <rep...@bugs.python.org> <http://bugs.python.org/issue30931> _______________________________________ _______________________________________________ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com