Add comments documenting gousb lifecycle management
Explain why we use gousb directly instead of antgo/driver/usb (libusb context leak on error paths), document the defer cleanup ordering, and note that errors are returned for graceful retry.
This commit is contained in:
parent
9efdfc9b83
commit
8a4457119a
@ -44,6 +44,11 @@ func resetAndWait(drv io.ReadWriter) error {
|
||||
func ListenForTrainer(vendorId uint16, productId uint16, deviceNumber uint32,
|
||||
events chan<- Event) error {
|
||||
|
||||
// Use gousb directly instead of antgo/driver/usb to manage context
|
||||
// lifecycle explicitly. The old code created a new gousb.Context on
|
||||
// every call via libusb_init and leaked it on error paths (device not
|
||||
// found, interface claim failure, etc.), which triggered a libusb
|
||||
// assertion after repeated ListenForTrainer calls.
|
||||
gctx := gousb.NewContext()
|
||||
defer gctx.Close()
|
||||
|
||||
@ -60,6 +65,9 @@ func ListenForTrainer(vendorId uint16, productId uint16, deviceNumber uint32,
|
||||
if err != nil {
|
||||
return fmt.Errorf("ant: claim interface: %w", err)
|
||||
}
|
||||
// Cleanup is ordered by defer stack: done() releases interface,
|
||||
// dev.Close() closes device, gctx.Close() closes context, cancel()
|
||||
// cancels the ANT message goroutine.
|
||||
defer done()
|
||||
|
||||
out, err := intf.OutEndpoint(1)
|
||||
@ -75,6 +83,8 @@ func ListenForTrainer(vendorId uint16, productId uint16, deviceNumber uint32,
|
||||
|
||||
logMsg("ant: device opened")
|
||||
|
||||
// Errors are returned (not panicked) so the caller can retry
|
||||
// gracefully instead of requiring a full process restart.
|
||||
if err := resetAndWait(drv); err != nil {
|
||||
return err
|
||||
}
|
||||
@ -85,6 +95,8 @@ func ListenForTrainer(vendorId uint16, productId uint16, deviceNumber uint32,
|
||||
|
||||
msgs := make(chan ant.BroadcastMessage, 100)
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
// cancel is the final defer in the stack, ensuring the ANT message
|
||||
// goroutine is torn down after all USB resources are released.
|
||||
defer cancel()
|
||||
go func() {
|
||||
device.DumpBroadcastMessages(ctx, drv, msgs)
|
||||
@ -124,6 +136,8 @@ func ListenForTrainer(vendorId uint16, productId uint16, deviceNumber uint32,
|
||||
}
|
||||
case <-time.After(10 * time.Second):
|
||||
logMsg("ant: no more messages arrived, restarting")
|
||||
// Return without error so the caller can retry gracefully
|
||||
// rather than panicking and requiring a full restart.
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user