Skip to content

Conversation

@gtsiam
Copy link
Contributor

@gtsiam gtsiam commented Jun 9, 2024

The issue with HidApi::new_without_enumerate() is that it makes both it and HidApi::new() potentially panic, with no way out in library contexts.

Instead, on platforms that need it, the same effect can be achieved by calling the newly added HidApi::disable_device_discovery() before any HidApi contexts are created.

@gtsiam gtsiam marked this pull request as draft June 9, 2024 10:25
@gtsiam gtsiam marked this pull request as ready for review June 9, 2024 10:54
@gtsiam gtsiam changed the title Remove Hidapi::new_without_enumerate(). Improved panic safety. Jun 19, 2024
@gtsiam
Copy link
Contributor Author

gtsiam commented Jun 7, 2025

This PR is approaching 1 Year old! Happy birthday! But also it's time to kill it cause I don't like seeing it in my backlog.

@ruabmbua Would you like me to get this into a clean state so we can merge it and be done with it Y/N?

@ruabmbua
Copy link
Owner

ruabmbua commented Jun 8, 2025

Honestly I think my response got lost in the ether, I remember I wrote something ...

Glancing over it again, you made a couple of modifications to build.rs, they do not actually have anything to do with what is described in the MR?

About the API change, it feels like the new API is a bit less "rust idiomatic", as it has more global state exposed in the API surface compared to before. Can we maybe resolve the panic issue while keeping the API more like before?

Also, do you have any concrete examples where its preferred to not panic? In my opinion if a problem can`t be handled, its totally ok to panic in rust.

Is it maybe that you consume hidapi in another library, and you do not want to have any panics reaching the user of your library?

gtsiam added 4 commits June 8, 2025 12:48
The issue with HidApi::new_without_enumerate() is that it makes both it
and HidApi::new() potentially panic, with no way out in library
contexts.

Instead, on platforms that need it, the same effect can be achieved by
calling HidApi::disable_device_discovery() before any HidApi contexts
are created in application code.

The intention is to eventually remove HidApi::new_without_enumerate().
@gtsiam
Copy link
Contributor Author

gtsiam commented Jun 8, 2025

Okay, since I actually got a response, I went ahead and fixed it up so we can talk about something concrete:

The main point of this PR:

  • Introduce HidApi::disable_device_discovery().: The library works the same way as it did before. The new function makes what was implicitly global state before, explicit. That's just the nature of working with C libraries.
  • Deprecate HidApi::new_without_enumerate().: Adds the deprecation notice. I don't know the next version, so I can't add a since = "..." here. The intention is to discourage use of it while favoring the explicit approach.

Housekeeping:

I'm just not gonna open one more PR that will never get merged and have to keep track off. It's the part I hate about the PR system, but I digress. Originally I had also split build.rs into a more manageable pieces rather than the current monolith - but I can't be bothered to do that again.


About the API change, it feels like the new API is a bit less "rust idiomatic", as it has more global state exposed in the API surface compared to before. Can we maybe resolve the panic issue while keeping the API more like before?

No. Not as long as you set global state in a C library in the backend. The global state is there in our dependencies and we can't pretend it's not. Maybe if you dive into libusb, figure out how it does device discovery and try to replicate it on the rust side? But I'm not personally interested in doing that work.

Also, do you have any concrete examples where its preferred to not panic? In my opinion if a problem can`t be handled, its totally ok to panic in rust.

I don't have a problem with panicking. I have a problem with panicking, effectively at random, in what should be a mostly infallible function for no good reason.

Imagine you're integrating a few libraries. Some use hidapi. Some libusb directly. Crappy device drivers and such. Now put yourself in the driver author's position:

impl MyDriver {
  fn new() -> Self {
    // Do I use new() or new_without_enumerate()? I don't know.
    // If another library has already been initialized before me,
    // one will panic, and one won't. Which? I don't know, it's a coin's toss.
    //
    // Or rely on the integrator to match the version of new that is called on every single library.
    // ...
    // That sounds like fun!
    let hidapi = HidApi::new();

    // ...
  }
}

@ruabmbua ruabmbua merged commit 009df08 into ruabmbua:main Jun 9, 2025
11 checks passed
@ruabmbua
Copy link
Owner

ruabmbua commented Jun 9, 2025

Thanks for revisiting the MR, I appreciate the work!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants