manuelbl / JavaDoesUSB

USB library for Java
MIT License
136 stars 10 forks source link

Strange NPE when opening USB device #21

Closed MariusVolkhart closed 1 month ago

MariusVolkhart commented 3 months ago

Hi,

I was hoping you could join me in exploring a strange NPE coming from inside the library.

My program keeps encountering the following error on MacOS.

java.lang.NullPointerException: Cannot invoke "jdk.internal.foreign.AbstractMemorySegmentImpl.isAlignedForElement(long, java.lang.foreign.MemoryLayout)" because "segment" is null
    at java.base/jdk.internal.foreign.LayoutPath.checkAlign(LayoutPath.java:290)
    at net.codecrete.usb.macos.IoKitHelper.getVtable(IoKitHelper.java:96)
    at net.codecrete.usb.macos.IoKitUsb.USBDeviceOpenSeize(IoKitUsb.java:54)
    at net.codecrete.usb.macos.MacosUsbDevice.open(MacosUsbDevice.java:115)

My application code is:

    private fun UsbDevice.openIfNeeded() {
        LOGGER.atDebug().log("USB device is open: {}.", isOpened)
        if (!isOpened) {
            try {
                open()
                try {
                    claimInterface(USB_INTERFACE_NUMBER)
                } catch (e: Exception) {
                    LOGGER.atWarn().withThrowable(e).log("Failed to claim interface")
                }
            } catch (e: Exception) {
                LOGGER.atWarn().withThrowable(e).log("Failed to open")
            }
        }
    }

I've bee experience this issue since 0.7.0 (first version I used). It happens after several hours of the application running. No USB devices added/removed. Restarting the application immediately makes it work. At no point does my application close the USB device. I added this openIfNeeded function because I found the USB device was releasing endpoints itself. As in, without me explicitly releasing them or closing the device, after several hours, I'd find the device to be unable to transferOut.

I don't know if I'm using the underlying USB library incorrectly (as in, should I not be holding the device open for hours on end without sending traffic), or if there's something else, but from a library perspective, I'd expect the open() call to not fail with an NPE :)

Please let me know if there's more information you'd like or something you'd like me to try out. Thanks for the fun FFM library!

Version: 1.0.0 MacOS Apple Silicon Java 22

manuel-ti8m commented 3 months ago

Thank you for reporting it. I will investigate it. It doesn't sound as if you are using the library incorrectly.

During the hours when the USB device is not used:

manuelbl commented 3 months ago

The same exception can be trigger when trying to open a device that was disconnected (the application kept it in a variable). The behavior has now been changed. It now triggers a UsbException that clearly indicates that the device has been disconnected.

I suspect that your case could be similar or the same, i.e. the USB device has been disconnected, if not physically, then by rebooting the USB device, USB hub or a similar action. At least macOS thinks it has been disconnected (and possibly reconnected).

The fixed code is on the main branch. It hasn't been published as a release it.

MariusVolkhart commented 1 month ago

Thanks for the analysis. Indeed, I made some code changes and open the USB on-demand now, and that resolves my issue. I haven't yet tried with the changes you made. I'm OK closing this ticket though. Again, thank you for responding and investigating.