Skip to content

driver_vive: fix infinite loop when closing HIDAPI devices - #369

Closed
m-va wants to merge 1 commit into
collabora:masterfrom
m-va:fix-hidapi-close-hang
Closed

driver_vive: fix infinite loop when closing HIDAPI devices#369
m-va wants to merge 1 commit into
collabora:masterfrom
m-va:fix-hidapi-close-hang

Conversation

@m-va

@m-va m-va commented Aug 17, 2026

Copy link
Copy Markdown

Fixes #312.

Problem

On Windows, USE_HIDAPI defaults to ON, and survive_vive_close() never
returns:

while (sv->udev_cnt) {          // never reaches 0
#ifndef HIDAPI
    libusb_handle_events(sv->usbctx);
#endif
    for (int i = 0; i < sv->udev_cnt; i++) {
        if (survive_handle_close_request_flag(sv->udev[i])) i--;
    }
}

survive_handle_close_request_flag() only acts when usbInfo->request_close
is set. In the HIDAPI backend that flag is raised only in HAPIReceiver() when
hid_read() returns a negative value; survive_close_usb_device() closes the
HID handles without setting it. The libusb backend is unaffected because
libusb_handle_events() drives the completion callbacks that raise the flag,
and that call is #ifndef HIDAPI.

Besides hanging the process, this also means config_save() — which runs later
inside survive_close() — is never reached, so lighthouse calibration is never
written to config.json and has to be redone on every launch.

Fix

Raise the flag (and mark the interfaces shut down, mirroring the libusb path)
when the device is actually closed. Freeing the handle there is safe because
survive_usb_handle_close() is a no-op in this backend.

Testing

Windows 11 x64, MSVC, master, USE_HIDAPI=ON, two Vive Trackers (2018) over
USB with SteamVR 2.0 base stations:

  • before: survive_simple_close() did not return after 60 s; config.json
    never contained lighthouse0/lighthouse1
  • after: it returns immediately, and config.json gets the lighthouse entries,
    so a second launch starts tracking without recalibrating

survive_vive_close() waits for every device to raise request_close, but the
HIDAPI backend only ever sets that flag from HAPIReceiver() when hid_read()
fails. survive_close_usb_device() closes the HID handles without setting it,
so the wait loop never terminates.

The libusb backend does not hit this because libusb_handle_events() drives the
transfer-completion callbacks that raise the flag, and that call is compiled
out under HIDAPI.

Set the flag when the device is closed. This also lets survive_close() reach
config_save(), so lighthouse calibration is persisted again instead of being
lost on every run.

Tested on Windows 11 x64 (MSVC, USE_HIDAPI=ON) with two Vive Trackers (2018)
over USB and SteamVR 2.0 base stations: survive_simple_close() goes from never
returning to completing immediately, and config.json gets its lighthouse0/1
entries so calibration survives a restart.

Fixes #312
@m-va m-va closed this by deleting the head repository Aug 18, 2026
@bl4ckb0ne

Copy link
Copy Markdown
Collaborator

Why was this closed @m-va ?

@m-va

m-va commented Aug 18, 2026

Copy link
Copy Markdown
Author

Sorry for the confusion — this was my mistake. I deleted my fork because I
misunderstood how forks are presented on GitHub, and that automatically closed
this PR. It was not intentional, and nothing is wrong with the patch itself.

Since the head repository is gone this PR can't be reopened, so I've re-forked
and will open a fresh PR with the same commit shortly. Apologies for the noise.

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

Labels

None yet

Development

Successfully merging this pull request may close these issues.

Infinite loop when shutting down vive driver

2 participants