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.

Author Mark.Williams
Recipients Mark.Williams, gvanrossum, vstinner, yselivanov
Date 2016年08月14日.00:26:44
SpamBayes Score -1.0
Marked as misclassified Yes
Message-id <1471134409.41.0.274513488512.issue27759@psf.upfronthosting.co.za>
In-reply-to
Content
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:
 sel.register(filedescriptor, selectors.EVENT_READ)
except OSError:
 traceback.print_exc()
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.
History
Date User Action Args
2016年08月14日 00:26:50Mark.Williamssetrecipients: + Mark.Williams, gvanrossum, vstinner, yselivanov
2016年08月14日 00:26:49Mark.Williamssetmessageid: <1471134409.41.0.274513488512.issue27759@psf.upfronthosting.co.za>
2016年08月14日 00:26:48Mark.Williamslinkissue27759 messages
2016年08月14日 00:26:46Mark.Williamscreate

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