-
Notifications
You must be signed in to change notification settings - Fork 901
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
libusb: remove the timeouts in hid_write() #190
base: master
Are you sure you want to change the base?
Conversation
Making this change fixes GEMakers/gea-sdk#2. |
dada9d3
to
0d4cf6c
Compare
I suppose this makes sense. Will merge. |
Great! Do you have an estimate on when you'll be able to merge it, perchance? |
Sorry to be a pest, but do you have an estimate on when you'll merge this? I ask because this fixes an real bug for us. Thank you! |
Actually, I'm thinking now that this may not be a good idea. There needs to be some kind of timeout so that applications don't hang forever when hardware misbehaves. Inside the Linux kernel, 5 seconds seems to be used frequently for this kind of thing. Would this work for your application? |
I don't understand -- setting a timeout of 5 seconds would keep the libusb implementation of hid_write() different than the other three:
Why should libusb/hid.c be different? |
I think you'll find that all of the implementations have a timeout. |
Hmm... looks like I'm wrong. It's been a while. linux/hid.c does timeout (write() will timeout in the kernel). The others block forever. Timeouts could easily be implemented on all the platforms and should be so that poorly-functioning (broken) devices don't hang the application, which I've observed. Alan. |
Agreed; timeouts could be implemented. But I think that the Linux hid_write() should be blocking so that it's like the others -- at least in this application, it is assumed that the hid_write() in libusb/hid.c behaves like the other 3. Perhaps a new function, hid_write_timeout() could expose timeout functionality? |
I missed your comment about linux/hid.c and the kernel timeout. How long does the kernel take to timeout? Is it more than 1 second? |
All the timeouts I've seen related to USB in the kernel are 5 seconds, iirc. |
Gotcha. How's this for a suggestion:
|
* linux: Use poll(2) to see if we can write before we actually write(2). Also add loop in hid_write() to make it infinite in case of timeout (per signal11#190). * libusb: Pass the milliseconds value to libusb_*_transfer() functions (adjusting for -1/0 differences). * windows: Currently returns -1. Needs to be written (by someone other than me). * mac: Currently returns -1. Needs to be written (by someone other than me).
New commit pushed to implement the suggestion. Note that I am not a Mac or Windows programmer -- the hid_write_timeout()'s for those two are currently hardwired to return -1. |
That's unfortunate then. |
The libusb/hid.c:hid_write() has timeouts in its calls to libusb_interrupt_transfer and libusb_control_transfer(). This timeout can sometimes be tripped (e.g., if the underlying hardware is slow), and no sensible error code is returned -- you just get a -1. Hence, the caller can't know that it could just try again because the only error that occurred was a timeout (or that the message may have actually gotten through). Additionally, the other hid.c:hid_write() implementations -- mac, and windows -- are all blocking and do not timeout. This makes the behavior of the libusb hid_write() different than the others, which seems weird. The linux/hid.c:hid_write() is seemingly blocking (because it uses a blocking write(2)), but it can timeout in the kernel. A follow on commit will make the linux hid.c: hid_write() behavior be truly blocking, too. This commit simply sets the libusb timeouts to 0 (i.e., infinite) to make the libusb hid_write() behave like the others.
If write() fails due to timeout, loop around and try again. This makes the linux/hid_write() exhibit the same blocking behavior as the other hid_write() implementations.
614c613
to
53d85c5
Compare
Ok, I removed the new hid_write_timeout() functions, and just make both the Linux and libusb versions of hid_write() be truly blocking. With these 2 commits, now all 4 versions of hid_write() are truly blocking. Someone else can add the hid_write_timeout() functions (to match the hid_read_timeout()) functions in a different PR. |
Blocking forever on writes is bad, like I said above. For example, see #198 What we really need is a consistent timeout across platforms. |
There are 2 related-but-different issues here:
A previous patch on this PR tried to (at least partially) address both issues by adding all 4 hid_write_timeout() implementations, but the Mac/Windows ones were just skeletons because I have no knowledge/experience on those systems (and no way to test them). You rejected that. So I removed the hid_write_timeout() interfaces and now this PR addresses just the first issue: making hid_write() be consistently blocking. In short: there are valid use cases for both hid_write_timeout() and hid_write() -- blocking is not always bad. I agree that adding hid_write_timeout() will fix #198. But fixing this bug should not be contingent upon also adding hid_write_timeout(), because that's a different issue. |
I feel dumb now. I didn't bother to read the existing PR's before adding my own. I'm sure yours is more well thought-out. I was mainly focused on the Windows implementation. |
@amullins83 Ah, you're referring to #199. Looks like you added hid_write_timeout() versions for everything except the Mac. Great! I still think these are related-but-different issues. There's some optional overlap because hid_write() may be able to be implemented in terms of hid_write_timeout(), but it doesn't have to be. |
@signal11 How about a nice Christmas present of merging this PR? :-) |
This is also causing issues for me due to the aforementioned GEMakers/gea-sdk#2. |
The libusb/hid.c:hid_write() has timeouts in its calls to libusb_interrupt_transfer and libusb_control_transfer(). This timeout can sometimes be tripped (e.g., if the underlying hardware is slow), and no sensible error code is returned -- you just get a -1. Hence, the caller can't know that it could just try again because the only error that occurred was a timeout (or that the message may have actually gotten through).
Additionally, the other hid.c:hid_write() implementations -- linux, mac, and windows -- are all blocking and do not timeout. This makes the behavior of the libusb hid_write() different than the others, which seems weird.
This commit simply sets the libusb timeouts to 0 (i.e., infinite) to make the libusb hid_write() behave like the others.