Elemecca / go-hotplug

Hardware Hotplug Detection for Go
Apache License 2.0
3 stars 0 forks source link

Changing from `DevIfHid` to `DevIfUnknown` results in `SIGSEGV: segmentation violation` #1

Open mrusme opened 1 month ago

mrusme commented 1 month ago

I was trying to change this part:

    listener, _ := hotplug.New(
        hotplug.DevIfHid,
        func(devIf *hotplug.DeviceInterface) {

into:

    listener, _ := hotplug.New(
        hotplug.DevIfUnknown,
        func(devIf *hotplug.DeviceInterface) {

In order to see if I can register a device being attached that otherwise would not. However, that change results in the application crashing with the following output:

panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x0 pc=0x5106fb]

goroutine 1 [running]:
github.com/elemecca/go-hotplug.(*Listener).listen.func2(0xc000037f00?)
    /home/mrus/.go/pkg/mod/github.com/elemecca/go-hotplug@v0.0.0-20231020015908-77bd9a5abc65/listener_udev.go:66 +0x1b
github.com/elemecca/go-hotplug.(*Listener).listen(0xc00009c300)
    /home/mrus/.go/pkg/mod/github.com/elemecca/go-hotplug@v0.0.0-20231020015908-77bd9a5abc65/listener_udev.go:68 +0x45
github.com/elemecca/go-hotplug.(*Listener).Listen(...)
    /home/mrus/.go/pkg/mod/github.com/elemecca/go-hotplug@v0.0.0-20231020015908-77bd9a5abc65/listener.go:25
main.main()

Aren't the classes outside of Hid supposed to work or did I miss to include something crucial? Thank you!

Elemecca commented 1 month ago

DevIfUnknown is the zero-value of the InterfaceClass enumeration. In the DeviceInterface object's Class property, it means that the library doesn't understand / support the class of that interface.

It looks like you're expecting that passing DevIfUnknown as the class filter to New will result in getting notifications for all interface classes.

Unfortunately, it's difficult to support listening for all interface classes: on Windows, the Enumerate method uses the CM_Get_Device_Interface_List function, which only works for a single interface class at a time. The Windows implementation would need to have an alternative version of Enumerate used when listening for all interface classes which instead does a depth-first walk of the entire device tree and queries the interface list for each device. That's not impossible, but it seems to me like a lot of work for something that wouldn't be that useful.

If you have a use case for listening on all interface classes, feel free to submit a separate feature request issue describing how you want to use it.

If you want to work with an interface class other than HID or Printer, please submit a feature request issue for each interface class you're interested in. It would be helpful if you could include the udev subsystem and devtype and the Windows device class GUID, but if you describe the device you want to find I can probably find them.

While passing DevIfUnknown to New is not supported, it shouldn't result in a segfault either.

On Linux with udev (which seems to be the platform you're using), New returns an error if you pass DevIfUnknown, but since it also still returns the Listener, and since the example code doesn't handle errors, it's hardly surprising that you missed that. New needs to be updated so that it returns an error and not a Listener on all platforms when DevIfUnknown is passed as the class filter.

Documentation should also be added / updated on DevIfUnknown and on New to indicate that using it as a filter is not supported.

mrusme commented 1 month ago

Thank you kindly for this detailed response, I appreciate your time and effort! <3

You are on point with your assumption, I was trying to get a different interface class other than HID/Printer working, namely XHCI-HCD USB Storage:

[ 1183.200254] usb 2-1: new SuperSpeed USB device number 2 using xhci_hcd
[ 1183.216944] usb 2-1: New USB device found, idVendor=1058, idProduct=262f, bcdDevice=50.02
[ 1183.216954] usb 2-1: New USB device strings: Mfr=2, Product=3, SerialNumber=1
[ 1183.216956] usb 2-1: Product: Game Drive
[ 1183.216959] usb 2-1: Manufacturer: Western Digital
[ 1183.216960] usb 2-1: SerialNumber: 57584D31453539343541434C
[ 1183.218015] usb-storage 2-1:1.0: USB Mass Storage device detected
[ 1183.218303] scsi host1: usb-storage 2-1:1.0
[ 1184.244012] scsi 1:0:0:0: Direct-Access     WD       Game Drive       5002 PQ: 0 ANSI: 6
[ 1184.244419] sd 1:0:0:0: Attached scsi generic sg1 type 0
[ 1184.246130] sd 1:0:0:0: [sdb] Spinning up disk...

You are also correct that I'm on Linux.

[...] and the Windows device class GUID

I'm not certain how to find that out, as I don't have access to Windows. I could set up a Windows 10 VM, but I would need some further directions in how to get that info, as I have 0 experience with Windows.

Thank you for the hints in regard to the segmentation fault!