Message298682
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 |
|
Date |
User |
Action |
Args |
2017-07-19 16:21:53 | Nir Soffer | set | recipients:
+ Nir Soffer, walkhour |
2017-07-19 16:21:53 | Nir Soffer | set | messageid: <1500481313.42.0.832550539482.issue30931@psf.upfronthosting.co.za> |
2017-07-19 16:21:53 | Nir Soffer | link | issue30931 messages |
2017-07-19 16:21:53 | Nir Soffer | create | |
|