-
Notifications
You must be signed in to change notification settings - Fork 114
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
UInput: Constructor can throw exception, leaving open a uinput fd #204
Comments
Simplest solution is to wrap the inner loop to avoid errors. def _find_device(self):
#:bug: the device node might not be immediately available
time.sleep(0.1)
for path in util.list_devices('/dev/input/'):
try:
d = device.InputDevice(path)
if d.name == self.name:
return d
except Exception:
pass |
Which Exception exactly? It would be better practice to specify the exact exception that we want to catch here |
You can not re-raise any exceptions there unless you rewrite the constructor to close the file descriptor before raising. The error is a |
Thanks. I guess it would make sense to commit this change to python-evdev, however, there might be more changes to this soon because of #205, so lets wait |
You have to catch all exceptions, not just file not found error, and not re-emit them since the inner loop crashing does not affect the class functionality. Exception does not include Keyboard Interrupts. There is also a race condition with Keyboard Interrupts but python evdev does not work correctly with those because it cleans up on free. |
Any other bug unrelated to the race condition of a missing devnode would be lost. Catching all exceptions is bad practice. If |
I will leave it up to you on how to handle the In order for this bug to be resolved, you either have to make sure you never throw on the Uinput constructor, or if you do, to close the file descriptor below before returning. According to the caller hint for #: An :class:`InputDevice <evdev.device.InputDevice>` instance
#: for the fake input device. ``None`` if the device cannot be
#: opened for reading and writing.
self.device = self._find_device() Even if that hides other bugs related to the |
Referencing the other thread, it may be preferable to completely rewrite Since the downstream device is not required for correct behavior, you should remove the I, for one, do not use those functions, so I monkey patch |
Or use a destructor class A:
def __del__(self):
print('__del__')
def foo(self):
raise Exception('foo')
A().foo() will print
In this destructor, the file descriptor could be closed. I wonder if this could break existing code. Would any project out there expect the uinput to remain open if the UInput object is garbage collected? |
I'm afraid this might break existing projects that handle errors that originate in |
But why again do we want to close the fd to |
Because that descriptor is stored on If the constructor throws, it can never be closed. |
Do destructors run if the init method does not finish? If it does it may be an option. |
ah, right, thanks.
yes |
Otherwise, try... except on the constructor. then raise e again |
destructor sounds cleaner to me. By the way, try:
raise Exception('foo')
finally:
print("finally") will print
|
You can not assume fd will exist in the destructor. But you can use something like the following. if hasattr(self, 'fd'):
fd = getattr(self, 'fd')
if fd:
os.close(fd) In general, destructors break KeyboardInterrupts so I had to remove Interrupts from my app (hhd). But they are convenient I will agree. |
Finally will run regardless, we do not want that. |
whoops |
At the end of the
uinput
constructor, it callsself._find_device()
.This function does the following:
If between
util.list_devices('/dev/input/'):
being called anddevice.InputDevice(path)
being called, the device ofpath
closes, this leads to a thrown exception.This exception propagates through the constructor, which has opened a filedescriptor from uinput. That fd never closes.
This leads to a duplicate device.
The text was updated successfully, but these errors were encountered: