-
Notifications
You must be signed in to change notification settings - Fork 84
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
HidDevice::drop is not thread safe on Windows #151
Comments
Hm this is a really weird issue. I don`t like the windows API design at all to be honest (having to cancel operations). Also I am very unfamiliar with the windows API in general. I think I am going to subscribe to the thread in the C library. Also maybe @sidit77 has any insights? |
Seems like a reasonable change. I think it's reasonable to match Microsoft in term of Windows version support. This means that the oldest supported version is 10.0.10240. In general I just copied the C library for the IO code to avoid intoducing new bugs. It wasn't a conscious decision to use I don't think the second call to The write function is also problematic, now that I think about it, as it doesn't cancel the write operation when it times out. I suspect the C library doesn't do it because it requires |
Fixes a use-after-free bug when dropping the HidDevice from a thread other than the one that was last used to read it, because of a pending async operation that did not get canceled. If the cancellation does not return an error, we get the overlapped result to block until it actually goes through. This is recommended by Microsoft in this example: <https://learn.microsoft.com/en-us/windows/win32/fileio/canceling-pending-i-o-operations#canceling-asynchronous-io>. Closes ruabmbua#151
I opened a PR that should properly cancel both the read and the write on drop, if anyone wants to give it a try. Should this be reported to rustsec? Since it can potentially corrupt memory. |
I came across this problem in my application and managed to write a minimal reproduce for it:
Click to expand
This simply consists of two threads, where one repeatedly opens and closes all connected devices, and the other tries to read all devices that are open. It only uses safe Rust, and only depends on hidapi 2.6.0, and when I run it with some custom HID devices connected, it crashes almost every time with either
(exit code: 0xc0000374, STATUS_HEAP_CORRUPTION)
or(exit code: 0xc0000005, STATUS_ACCESS_VIOLATION)
. This happens with or without thewindows-native
feature.I believe this is due to the fact that the
Drop
implementation calls CancelIo, which only cancels I/O operations started on the calling thread. I think it should use CancelIoEx instead.With the
windows-native
feature enabled and the following patch, it did not crash during my 30+ tests:Click to expand
This has been a topic of discussion in the original C library for many years (see for example libusb/hidapi#133 and signal11/hidapi#48), but I believe it is the correct solution at least for the Rust crate. I wasn't able to test if the other call to
CancelIo
needs to be changed toCancelIoEx
as well, since my application only reads and writes from one thread.For completeness, although I don't think it matters, I ran these tests on Windows 11 Pro, Version 23H2.
The text was updated successfully, but these errors were encountered: