New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
selectors incorrectly retain invalid file descriptors #71946
Comments
Registering a file descriptor with EpollSelector.register that epoll(7) refuses results in the selector retaining a SelectorKey for that file descriptor, even though it's not monitored. The following program attempts to register a file on the filesystem with an EpollSelector. epoll_ctl(2) returns EPERM when given a such a file descriptor, so it shouldn't be registered with the selector, but it is registered. import selectors
import tempfile
import traceback
sel = selectors.EpollSelector()
with tempfile.TemporaryFile() as f:
try:
sel.register(f, selectors.EVENT_READ)
except PermissionError:
traceback.print_exc()
print("This should have raised a KeyError:", sel.get_key(f)) It produces this output on Pythons 3.4-3.6: Traceback (most recent call last):
File "/tmp/sel.py", line 9, in <module>
sel.register(f, selectors.EVENT_READ)
File "/usr/lib/python3.4/selectors.py", line 402, in register
self._epoll.register(key.fd, epoll_events)
PermissionError: [Errno 1] Operation not permitted
This should have raised a KeyError: SelectorKey(fileobj=<_io.BufferedRandom name=8>, fd=8, events=1, data=None) A similar problem exists with KqueueSelector. Consider the following program: import selectors
import tempfile
import traceback
sel = selectors.KqueueSelector()
f = tempfile.TemporaryFile()
filedescriptor = f.fileno()
f.close() try: print("This should have raised a KeyError:", sel.get_key(filedescriptor)) In this case selectors._fileobj_to_fd doesn't detect that the integer file descriptor is closed. Note that _fileobj_to_fd should not be changed! Attempting to use, say, fcntl(fd, fcntl.GET_FD) to detect a closed file descriptor introduces a TOCTTOU bug. Another thread (or another process, if the file descriptor refers to a socket shared between two or more processes and one calls shutdown(2) on it) can change the state of the file descriptor between the time it's checked and the time it's registered. A new file might even be opened and given the previous file descriptor. The attached patch catches any exception raised by EpollSelector.register or KqueueSelector.register, removes the SelectorKey from BaseSelector's table, and then re-raises the exception. Note that I've included asyncio as an affected component, because asyncio wraps the selectors module. |
Your patch doesn't apply cleanly to the 3.4 or 3.5 branches -- how did you generate it? |
Whoops! I pulled from https://github.com/python/cpython and branched off of master. The previous commit was https://github.com/python/cpython/tree/043152b8da83105ff5cba88d4e6ef1d5c64b3602 I can generate new patches using hg.python.org's 3.4 and 3.5 branches. Please stand by. |
We only need 3.5; 3.4 is no longer supported. |
Also don't spend more time on this, I found a way to apply the patch |
OK! Sorry for the trouble. On Sat, Aug 13, 2016 at 6:17 PM, Guido van Rossum <report@bugs.python.org>
|
Regenerated patch to get a review button. |
New changeset 8944fd09b9ca by Yury Selivanov in branch '3.5': New changeset 08a75f380699 by Yury Selivanov in branch '3.6': New changeset ded64b96a4e7 by Yury Selivanov in branch 'default': |
I've fixed the remaining review comments & committed the patch. Thank you Mark! BTW, this also fixes http://bugs.python.org/issue27386. |
New changeset 8cc1fca83fb8 by Yury Selivanov in branch '3.4': |
Misc/NEWS
so that it is managed by towncrier #552Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.
Show more details
GitHub fields:
bugs.python.org fields:
The text was updated successfully, but these errors were encountered: