Closed AstraLuma closed 8 years ago
Thanks for this report.
I suspect instance cleanup happens in the wrong order. Could you confirm this by running:
$ ltrace -o stressball.ltrace -l "libusb*" python stressball.py
and pasting the output here ?
O/T: I like the idea of using a context manager for claiming & releasing interface.
...actually, looking better at the trace I generated from a sample script, it is missing a lot of calls. Looks like you also must pass -x "libusb*"
:
$ ltrace -o stressball.ltrace -x "libusb*" -l "libusb*" python stressball.py
--- SIGCHLD (Child exited) ---
--- SIGCHLD (Child exited) ---
libusb_init@libusb-1.0.so.0(0x7f67cd956808, 19, 1, 1 <unfinished ...>
libusb-1.0.so.0->libusb_has_capability(1, 0x7f67d1128af4, 0, 0 <unfinished ...>
libusb_has_capability@libusb-1.0.so.0(1, 0x7f67d1128af4, 0, 0) = 1
<... libusb_has_capability resumed> ) = 1
libusb-1.0.so.0->libusb_has_capability(1, 0, 0xe822b0, 0 <unfinished ...>
libusb_has_capability@libusb-1.0.so.0(1, 0, 0xe822b0, 0) = 1
<... libusb_has_capability resumed> ) = 1
libusb-1.0.so.0->libusb_has_capability(1, 0x7f67d1128af4, 0, 0 <unfinished ...>
libusb_has_capability@libusb-1.0.so.0(1, 0x7f67d1128af4, 0, 0) = 1
<... libusb_has_capability resumed> ) = 1
libusb-1.0.so.0->libusb_ref_device(0xfdaf80, 0xfe45d0, 0, 0 <unfinished ...>
libusb_ref_device@libusb-1.0.so.0(0xfdaf80, 0xfe45d0, 0, 0) = 0xfdaf80
<... libusb_ref_device resumed> ) = 0xfdaf80
libusb-1.0.so.0->libusb_has_capability(1, 0, 0xe822b0, 0 <unfinished ...>
libusb_has_capability@libusb-1.0.so.0(1, 0, 0xe822b0, 0) = 1
<... libusb_has_capability resumed> ) = 1
libusb-1.0.so.0->libusb_has_capability(1, 0x7f67d1128af4, 0, 0 <unfinished ...>
libusb_has_capability@libusb-1.0.so.0(1, 0x7f67d1128af4, 0, 0) = 1
<... libusb_has_capability resumed> ) = 1
libusb-1.0.so.0->libusb_ref_device(0xf72200, 0xfd9450, 0, 0 <unfinished ...>
libusb_ref_device@libusb-1.0.so.0(0xf72200, 0xfd9450, 0, 0) = 0xf72200
<... libusb_ref_device resumed> ) = 0xf72200
libusb-1.0.so.0->libusb_has_capability(1, 0, 0xe822b0, 0 <unfinished ...>
libusb_has_capability@libusb-1.0.so.0(1, 0, 0xe822b0, 0) = 1
<... libusb_has_capability resumed> ) = 1
libusb-1.0.so.0->libusb_has_capability(1, 0x7f67d1128af4, 0, 0 <unfinished ...>
libusb_has_capability@libusb-1.0.so.0(1, 0x7f67d1128af4, 0, 0) = 1
<... libusb_has_capability resumed> ) = 1
libusb-1.0.so.0->libusb_has_capability(1, 0, 0xe822b0, 0 <unfinished ...>
libusb_has_capability@libusb-1.0.so.0(1, 0, 0xe822b0, 0) = 1
<... libusb_has_capability resumed> ) = 1
libusb-1.0.so.0->libusb_has_capability(1, 0x7f67d1128af4, 0, 0 <unfinished ...>
libusb_has_capability@libusb-1.0.so.0(1, 0x7f67d1128af4, 0, 0) = 1
<... libusb_has_capability resumed> ) = 1
libusb-1.0.so.0->libusb_ref_device(0x1009ae0, 0xfd7130, 0, 0 <unfinished ...>
libusb_ref_device@libusb-1.0.so.0(0x1009ae0, 0xfd7130, 0, 0) = 0x1009ae0
<... libusb_ref_device resumed> ) = 0x1009ae0
libusb-1.0.so.0->libusb_has_capability(1, 0, 0xe822b0, 0 <unfinished ...>
libusb_has_capability@libusb-1.0.so.0(1, 0, 0xe822b0, 0) = 1
<... libusb_has_capability resumed> ) = 1
libusb-1.0.so.0->libusb_has_capability(1, 0x7f67d1128af4, 0, 0 <unfinished ...>
libusb_has_capability@libusb-1.0.so.0(1, 0x7f67d1128af4, 0, 0) = 1
<... libusb_has_capability resumed> ) = 1
libusb-1.0.so.0->libusb_ref_device(0xef0b00, 0xfd8390, 0, 0 <unfinished ...>
libusb_ref_device@libusb-1.0.so.0(0xef0b00, 0xfd8390, 0, 0) = 0xef0b00
<... libusb_ref_device resumed> ) = 0xef0b00
libusb-1.0.so.0->libusb_has_capability(1, 0, 0xe822b0, 0 <unfinished ...>
libusb_has_capability@libusb-1.0.so.0(1, 0, 0xe822b0, 0) = 1
<... libusb_has_capability resumed> ) = 1
<... libusb_init resumed> ) = 0
libusb_get_device_list@libusb-1.0.so.0(0xe82290, 0x7f67cd956890, 0xfc5e18, 0x7f67d028c048 <unfinished ...>
libusb-1.0.so.0->libusb_has_capability(1, 4, 0x7f67cdfbdee0, 0x7f67cdfbd373 <unfinished ...>
libusb_has_capability@libusb-1.0.so.0(1, 4, 0x7f67cdfbdee0, 0x7f67cdfbd373) = 1
<... libusb_has_capability resumed> ) = 1
libusb-1.0.so.0->libusb_ref_device(0xef0bc0, 0xef0bc0, 0xef0c10, 0 <unfinished ...>
libusb_ref_device@libusb-1.0.so.0(0xef0bc0, 0xef0bc0, 0xef0c10, 0) = 0xef0bc0
<... libusb_ref_device resumed> ) = 0xef0bc0
libusb-1.0.so.0->libusb_ref_device(0xef0b00, 0xef0b00, 0xef0b50, 0 <unfinished ...>
libusb_ref_device@libusb-1.0.so.0(0xef0b00, 0xef0b00, 0xef0b50, 0) = 0xef0b00
<... libusb_ref_device resumed> ) = 0xef0b00
libusb-1.0.so.0->libusb_ref_device(0x1009ae0, 0x1009ae0, 0x1009b30, 0 <unfinished ...>
libusb_ref_device@libusb-1.0.so.0(0x1009ae0, 0x1009ae0, 0x1009b30, 0) = 0x1009ae0
<... libusb_ref_device resumed> ) = 0x1009ae0
libusb-1.0.so.0->libusb_ref_device(0x100c9d0, 0x100c9d0, 0x100ca20, 0 <unfinished ...>
libusb_ref_device@libusb-1.0.so.0(0x100c9d0, 0x100c9d0, 0x100ca20, 0) = 0x100c9d0
<... libusb_ref_device resumed> ) = 0x100c9d0
libusb-1.0.so.0->libusb_ref_device(0xf72200, 0xf72200, 0xf72250, 0 <unfinished ...>
libusb_ref_device@libusb-1.0.so.0(0xf72200, 0xf72200, 0xf72250, 0) = 0xf72200
<... libusb_ref_device resumed> ) = 0xf72200
libusb-1.0.so.0->libusb_ref_device(0xfdaf80, 0xfdaf80, 0xfdafd0, 0 <unfinished ...>
libusb_ref_device@libusb-1.0.so.0(0xfdaf80, 0xfdaf80, 0xfdafd0, 0) = 0xfdaf80
<... libusb_ref_device resumed> ) = 0xfdaf80
libusb-1.0.so.0->libusb_ref_device(0xef0bc0, 2, 56, 7 <unfinished ...>
libusb_ref_device@libusb-1.0.so.0(0xef0bc0, 2, 56, 7) = 0xef0bc0
<... libusb_ref_device resumed> ) = 0xef0bc0
libusb-1.0.so.0->libusb_ref_device(0xef0b00, 0, 0xef0bc0, 0 <unfinished ...>
libusb_ref_device@libusb-1.0.so.0(0xef0b00, 0, 0xef0bc0, 0) = 0xef0b00
<... libusb_ref_device resumed> ) = 0xef0b00
libusb-1.0.so.0->libusb_ref_device(0x1009ae0, 0, 0xef0b00, 0 <unfinished ...>
libusb_ref_device@libusb-1.0.so.0(0x1009ae0, 0, 0xef0b00, 0) = 0x1009ae0
<... libusb_ref_device resumed> ) = 0x1009ae0
libusb-1.0.so.0->libusb_ref_device(0x100c9d0, 0, 0x1009ae0, 0 <unfinished ...>
libusb_ref_device@libusb-1.0.so.0(0x100c9d0, 0, 0x1009ae0, 0) = 0x100c9d0
<... libusb_ref_device resumed> ) = 0x100c9d0
libusb-1.0.so.0->libusb_ref_device(0xf72200, 0, 0x100c9d0, 0 <unfinished ...>
libusb_ref_device@libusb-1.0.so.0(0xf72200, 0, 0x100c9d0, 0) = 0xf72200
<... libusb_ref_device resumed> ) = 0xf72200
libusb-1.0.so.0->libusb_ref_device(0xfdaf80, 0, 0xf72200, 0 <unfinished ...>
libusb_ref_device@libusb-1.0.so.0(0xfdaf80, 0, 0xf72200, 0) = 0xfdaf80
<... libusb_ref_device resumed> ) = 0xfdaf80
libusb-1.0.so.0->libusb_unref_device(0xef0bc0, 0, 0xfdaf80, 0 <unfinished ...>
libusb_unref_device@libusb-1.0.so.0(0xef0bc0, 0, 0xfdaf80, 0) = 0
<... libusb_unref_device resumed> ) = 0
libusb-1.0.so.0->libusb_unref_device(0xef0b00, 0, 0xef0bc0, 0 <unfinished ...>
libusb_unref_device@libusb-1.0.so.0(0xef0b00, 0, 0xef0bc0, 0) = 0
<... libusb_unref_device resumed> ) = 0
libusb-1.0.so.0->libusb_unref_device(0x1009ae0, 0, 0xef0b00, 0 <unfinished ...>
libusb_unref_device@libusb-1.0.so.0(0x1009ae0, 0, 0xef0b00, 0) = 0
<... libusb_unref_device resumed> ) = 0
libusb-1.0.so.0->libusb_unref_device(0x100c9d0, 0, 0x1009ae0, 0 <unfinished ...>
libusb_unref_device@libusb-1.0.so.0(0x100c9d0, 0, 0x1009ae0, 0) = 0
<... libusb_unref_device resumed> ) = 0
libusb-1.0.so.0->libusb_unref_device(0xf72200, 0, 0x100c9d0, 0 <unfinished ...>
libusb_unref_device@libusb-1.0.so.0(0xf72200, 0, 0x100c9d0, 0) = 0
<... libusb_unref_device resumed> ) = 0
libusb-1.0.so.0->libusb_unref_device(0xfdaf80, 0, 0xf72200, 0 <unfinished ...>
libusb_unref_device@libusb-1.0.so.0(0xfdaf80, 0, 0xf72200, 0) = 0
<... libusb_unref_device resumed> ) = 0
<... libusb_get_device_list resumed> ) = 6
libusb_ref_device@libusb-1.0.so.0(0xef0bc0, 0xb94d58a73c9afc00, 0xfc4d98, 0x7f67d0299b40) = 0xef0bc0
libusb_get_device_descriptor@libusb-1.0.so.0(0xef0bc0, 0xf1d230, 0xfbc6e8, 0x7f67d0299b40) = 0
libusb_get_config_descriptor@libusb-1.0.so.0(0xef0bc0, 0, 0x7f67cd956de0, 0x7f67d13b6b76) = 0
libusb_ref_device@libusb-1.0.so.0(0xef0b00, 0xb94d58a73c9afc00, 0xfc4d98, 0x7f67d0299b40) = 0xef0b00
libusb_get_device_descriptor@libusb-1.0.so.0(0xef0b00, 0xf1d3d0, 0xfbc6e8, 0x7f67d0299b40) = 0
libusb_get_config_descriptor@libusb-1.0.so.0(0xef0b00, 0, 0x7f67cd958120, 0x7f67d13b6b76) = 0
libusb_ref_device@libusb-1.0.so.0(0x1009ae0, 0xb94d58a73c9afc00, 0xfc4d98, 0x7f67d0299b40) = 0x1009ae0
libusb_get_device_descriptor@libusb-1.0.so.0(0x1009ae0, 0x1004700, 0xfbc6e8, 0x7f67d0299b40) = 0
libusb_get_config_descriptor@libusb-1.0.so.0(0x1009ae0, 0, 0x7f67cd9583c8, 0x7f67d13b6b76) = 0
libusb_ref_device@libusb-1.0.so.0(0x100c9d0, 0xb94d58a73c9afc00, 0xfc4d98, 0x7f67d0299b40) = 0x100c9d0
libusb_get_device_descriptor@libusb-1.0.so.0(0x100c9d0, 0xef0ae0, 0xfbc6e8, 0x7f67d0299b40) = 0
libusb_get_config_descriptor@libusb-1.0.so.0(0x100c9d0, 0, 0x7f67cd958670, 0x7f67d13b6b76) = 0
libusb_ref_device@libusb-1.0.so.0(0xf72200, 0xb94d58a73c9afc00, 0xfc4d98, 0x7f67d0299b40) = 0xf72200
libusb_get_device_descriptor@libusb-1.0.so.0(0xf72200, 0xfb1160, 0xfbc6e8, 0x7f67d0299b40) = 0
libusb_get_config_descriptor@libusb-1.0.so.0(0xf72200, 0, 0x7f67cd958918, 0x7f67d13b6b76) = 0
libusb_ref_device@libusb-1.0.so.0(0xfdaf80, 0xb94d58a73c9afc00, 0xfc4d98, 0x7f67d0299b40) = 0xfdaf80
libusb_get_device_descriptor@libusb-1.0.so.0(0xfdaf80, 0x100d790, 0xfbc6e8, 0x7f67d0299b40) = 0
libusb_get_config_descriptor@libusb-1.0.so.0(0xfdaf80, 0, 0x7f67cd958bc0, 0x7f67d13b6b76) = 0
libusb_free_device_list@libusb-1.0.so.0(0x1009690, 1, 0xf04b98, 0x7f67d0299b40 <unfinished ...>
libusb-1.0.so.0->libusb_unref_device(0xef0bc0, 1, 0xf04b98, 0x7f67d0299b40 <unfinished ...>
libusb_unref_device@libusb-1.0.so.0(0xef0bc0, 1, 0xf04b98, 0x7f67d0299b40) = 0
<... libusb_unref_device resumed> ) = 0
libusb-1.0.so.0->libusb_unref_device(0xef0b00, 0, 0xef0bc0, 0 <unfinished ...>
libusb_unref_device@libusb-1.0.so.0(0xef0b00, 0, 0xef0bc0, 0) = 0
<... libusb_unref_device resumed> ) = 0
libusb-1.0.so.0->libusb_unref_device(0x1009ae0, 0, 0xef0b00, 0 <unfinished ...>
libusb_unref_device@libusb-1.0.so.0(0x1009ae0, 0, 0xef0b00, 0) = 0
<... libusb_unref_device resumed> ) = 0
libusb-1.0.so.0->libusb_unref_device(0x100c9d0, 0, 0x1009ae0, 0 <unfinished ...>
libusb_unref_device@libusb-1.0.so.0(0x100c9d0, 0, 0x1009ae0, 0) = 0
<... libusb_unref_device resumed> ) = 0
libusb-1.0.so.0->libusb_unref_device(0xf72200, 0, 0x100c9d0, 0 <unfinished ...>
libusb_unref_device@libusb-1.0.so.0(0xf72200, 0, 0x100c9d0, 0) = 0
<... libusb_unref_device resumed> ) = 0
libusb-1.0.so.0->libusb_unref_device(0xfdaf80, 0, 0xf72200, 0 <unfinished ...>
libusb_unref_device@libusb-1.0.so.0(0xfdaf80, 0, 0xf72200, 0) = 0
<... libusb_unref_device resumed> ) = 0
<... libusb_free_device_list resumed> ) = 0x1007f50
libusb_unref_device@libusb-1.0.so.0(0xfdaf80, 0xb94d58a73c9afc00, 0xfc4d98, 0x7f67d028c048) = 0
libusb_free_config_descriptor@libusb-1.0.so.0(0xfe4590, 0xb94d58a73c9afc00, 0xfc2588, 0x7f67d028c048) = 0xfe45b0
libusb_unref_device@libusb-1.0.so.0(0xf72200, 0xb94d58a73c9afc00, 0xfc4d98, 0x7f67d028c048) = 0
libusb_free_config_descriptor@libusb-1.0.so.0(0x100d1e0, 0xb94d58a73c9afc00, 0xfc2588, 0x7f67d028c048) = 0x100d200
libusb_unref_device@libusb-1.0.so.0(0x100c9d0, 0xb94d58a73c9afc00, 0xfc4d98, 0x7f67d028c048) = 0
libusb_free_config_descriptor@libusb-1.0.so.0(0x100d360, 0xb94d58a73c9afc00, 0xfc2588, 0x7f67d028c048) = 0x100d380
libusb_unref_device@libusb-1.0.so.0(0x1009ae0, 0xb94d58a73c9afc00, 0xfc4d98, 0x7f67d028c048) = 0
libusb_free_config_descriptor@libusb-1.0.so.0(0x1007f30, 0xb94d58a73c9afc00, 0xfc2588, 0x7f67d028c048) = 0x100af50
libusb_unref_device@libusb-1.0.so.0(0xef0b00, 0xb94d58a73c9afc00, 0xfc4d98, 0x7f67d028c048) = 0
libusb_free_config_descriptor@libusb-1.0.so.0(0xe963e0, 0xb94d58a73c9afc00, 0xfc2588, 0x7f67d028c048) = 0xfd6760
libusb_open@libusb-1.0.so.0(0xef0bc0, 0x7f67cd956f78, 0xfc6da8, 0x7f67d028c048 <unfinished ...>
libusb-1.0.so.0->libusb_ref_device(0xef0bc0, 0x7f67d1128af4, 0, 0 <unfinished ...>
libusb_ref_device@libusb-1.0.so.0(0xef0bc0, 0x7f67d1128af4, 0, 0) = 0xef0bc0
<... libusb_ref_device resumed> ) = 0xef0bc0
<... libusb_open resumed> ) = 0
libusb_set_auto_detach_kernel_driver@libusb-1.0.so.0(0xf044c0, 1, 0xf04b98, 0x7f67d0299b88) = 0
libusb_claim_interface@libusb-1.0.so.0(0xf044c0, 0, 0xf04b98, 0x7f67d0299b88) = 0
libusb_control_transfer@libusb-1.0.so.0(0xf044c0, 33, 9, 512 <unfinished ...>
libusb-1.0.so.0->libusb_alloc_transfer(0, 33, 9, 512 <unfinished ...>
libusb_alloc_transfer@libusb-1.0.so.0(0, 33, 9, 512) = 0x100b648
<... libusb_alloc_transfer resumed> ) = 0x100b648
libusb-1.0.so.0->libusb_submit_transfer(0x100b648, 0x7f67cd9569a0, 8, 0 <unfinished ...>
libusb_submit_transfer@libusb-1.0.so.0(0x100b648, 0x7f67cd9569a0, 8, 0 <unfinished ...>
libusb-1.0.so.0->libusb_ref_device(0xef0bc0, 0, 0xe82358, 0x7f67d0e5d76a <unfinished ...>
libusb_ref_device@libusb-1.0.so.0(0xef0bc0, 0, 0xe82358, 0x7f67d0e5d76a) = 0xef0bc0
<... libusb_ref_device resumed> ) = 0xef0bc0
<... libusb_submit_transfer resumed> ) = 0
<... libusb_submit_transfer resumed> ) = 0
libusb-1.0.so.0->libusb_handle_events_completed(0xe82290, 0x7fffa13df534, 0x100b5f8, 0 <unfinished ...>
libusb_handle_events_completed@libusb-1.0.so.0(0xe82290, 0x7fffa13df534, 0x100b5f8, 0 <unfinished ...>
libusb-1.0.so.0->libusb_handle_events_timeout_completed(0xe82290, 0x7fffa13df4b0, 0x7fffa13df534, 0 <unfinished ...>
libusb_handle_events_timeout_completed@libusb-1.0.so.0(0xe82290, 0x7fffa13df4b0, 0x7fffa13df534, 0 <unfinished ...>
libusb-1.0.so.0->libusb_get_next_timeout(0xe82290, 0x7fffa13df420, 0x7fffa13df460, 0 <unfinished ...>
libusb_get_next_timeout@libusb-1.0.so.0(0xe82290, 0x7fffa13df420, 0x7fffa13df460, 0) = 0
<... libusb_get_next_timeout resumed> ) = 0
libusb-1.0.so.0->libusb_try_lock_events(0xe82290, 0x7fffa13df420, 0, 0 <unfinished ...>
libusb_try_lock_events@libusb-1.0.so.0(0xe82290, 0x7fffa13df420, 0, 0) = 0
<... libusb_try_lock_events resumed> ) = 0
libusb-1.0.so.0->libusb_unref_device(0xef0bc0, 4, 0x7f67cdfbf590, 0x7f67cdfbf9ea <unfinished ...>
libusb_unref_device@libusb-1.0.so.0(0xef0bc0, 4, 0x7f67cdfbf590, 0x7f67cdfbf9ea) = 0
<... libusb_unref_device resumed> ) = 0
libusb-1.0.so.0->libusb_unlock_events(0xe82290, 0, 0xe822e8, -104 <unfinished ...>
libusb_unlock_events@libusb-1.0.so.0(0xe82290, 0, 0xe822e8, -104) = 0
<... libusb_unlock_events resumed> ) = 0
<... libusb_handle_events_timeout_completed resumed> ) = 0
<... libusb_handle_events_timeout_completed resumed> ) = 0
<... libusb_handle_events_completed resumed> ) = 0
<... libusb_handle_events_completed resumed> ) = 0
libusb-1.0.so.0->libusb_free_transfer(0x100b648, 0, 0xffffffffffff8aa4, 0 <unfinished ...>
libusb_free_transfer@libusb-1.0.so.0(0x100b648, 0, 0xffffffffffff8aa4, 0) = 1
<... libusb_free_transfer resumed> ) = 1
<... libusb_control_transfer resumed> ) = 0xfffffff8
libusb_release_interface@libusb-1.0.so.0(0xf044c0, 0, 0xf04b98, 0x7f67d0299b88) = 0
libusb_exit@libusb-1.0.so.0(0xe82290, 0xb94d58a73c9afc00, 0xfc3dd8, 0x7f67d0615c18 <unfinished ...>
libusb-1.0.so.0->libusb_has_capability(1, 0, 0x7f67ce1c5420, 0 <unfinished ...>
libusb_has_capability@libusb-1.0.so.0(1, 0, 0x7f67ce1c5420, 0) = 1
<... libusb_has_capability resumed> ) = 1
libusb-1.0.so.0->libusb_unref_device(0xef0bc0, 0, 0xe822a0, 0 <unfinished ...>
libusb_unref_device@libusb-1.0.so.0(0xef0bc0, 0, 0xe822a0, 0) = 0
<... libusb_unref_device resumed> ) = 0
libusb-1.0.so.0->libusb_unref_device(0xef0b00, 0, 0xe822a0, 0 <unfinished ...>
libusb_unref_device@libusb-1.0.so.0(0xef0b00, 0, 0xe822a0, 0) = 0
<... libusb_unref_device resumed> ) = 0
libusb-1.0.so.0->libusb_unref_device(0x1009ae0, 0, 0xe822a0, 0 <unfinished ...>
libusb_unref_device@libusb-1.0.so.0(0x1009ae0, 0, 0xe822a0, 0) = 0
<... libusb_unref_device resumed> ) = 0
libusb-1.0.so.0->libusb_unref_device(0x100c9d0, 0, 0xe822a0, 0 <unfinished ...>
libusb_unref_device@libusb-1.0.so.0(0x100c9d0, 0, 0xe822a0, 0 <unfinished ...>
libusb-1.0.so.0->libusb_unref_device(0xf72200, 0x7f67cdfbd358, 1, 85 <unfinished ...>
libusb_unref_device@libusb-1.0.so.0(0xf72200, 0x7f67cdfbd358, 1, 85) = 0
<... libusb_unref_device resumed> ) = 0
libusb-1.0.so.0->libusb_has_capability(1, 0, 0xffffffff, 0xf6c710 <unfinished ...>
libusb_has_capability@libusb-1.0.so.0(1, 0, 0xffffffff, 0xf6c710) = 1
<... libusb_has_capability resumed> ) = 1
<... libusb_unref_device resumed> ) = 1
<... libusb_unref_device resumed> ) = 1
libusb-1.0.so.0->libusb_unref_device(0xf72200, 0, 0xe822a0, 0xf6c710 <unfinished ...>
libusb_unref_device@libusb-1.0.so.0(0xf72200, 0, 0xe822a0, 0xf6c710 <unfinished ...>
libusb-1.0.so.0->libusb_unref_device(0xfdaf80, 0x7f67cdfbd358, 1, 85 <unfinished ...>
libusb_unref_device@libusb-1.0.so.0(0xfdaf80, 0x7f67cdfbd358, 1, 85) = 0
<... libusb_unref_device resumed> ) = 0
libusb-1.0.so.0->libusb_has_capability(1, 0, 0xffffffff, 0 <unfinished ...>
libusb_has_capability@libusb-1.0.so.0(1, 0, 0xffffffff, 0) = 1
<... libusb_has_capability resumed> ) = 1
<... libusb_unref_device resumed> ) = 1
<... libusb_unref_device resumed> ) = 1
libusb-1.0.so.0->libusb_unref_device(0xfdaf80, 0, 0xe822a0, 0 <unfinished ...>
libusb_unref_device@libusb-1.0.so.0(0xfdaf80, 0, 0xe822a0, 0 <unfinished ...>
libusb-1.0.so.0->libusb_unref_device(0, 0x7f67cdfbd358, 1, 85 <unfinished ...>
libusb_unref_device@libusb-1.0.so.0(0, 0x7f67cdfbd358, 1, 85) = 0
<... libusb_unref_device resumed> ) = 0
libusb-1.0.so.0->libusb_has_capability(1, 0, 0xffffffff, 0xf72290 <unfinished ...>
libusb_has_capability@libusb-1.0.so.0(1, 0, 0xffffffff, 0xf72290) = 1
<... libusb_has_capability resumed> ) = 1
<... libusb_unref_device resumed> ) = 1
<... libusb_unref_device resumed> ) = 1
<... libusb_exit resumed> ) = 0
libusb_close@libusb-1.0.so.0(0xf044c0, 0xb94d58a73c9afc00, 0xfc6258, 0x7f67d0615c18 <no return ...>
--- SIGINT (Interrupt) ---
+++ killed by SIGINT +++
Aha, libusb_exit indeed returned before libusb_close got called. So there is something weird about the order in which python 3[.5 specifically ?] garbage-collects on interpreter shutdown.
If you just want to work around this issue to continue debugging the one you were initially chasing, you can wrap your with
-block in a try..except
block ending like this:
except KeyboardInterrupt:
handle.close()
(which makes me wonder about making USBDeviceHandle a context manager...) It should be enough to reach the correct execution order.
This said, python-usb1 already give a hint to the interpreter by referencing the USBContext instance from USBDeviceHandle - it should then garbage-collect the handle before the context. Unless there is somehow a reference loop, which I do not see yet.
Another off-topic: I spotted the REQUEST_TYPE_CLASS constant declaration, and indeed there was a mistake in python-libusb1 as it defined these constants as TYPE_CLASS (etc). I see this changed in 2008 in libusb, and I picked the old names.
I could reproduce the behaviour in a nutshell:
$ python3
Python 3.5.1+ (default, Mar 30 2016, 22:46:26)
[GCC 5.3.1 20160323] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> class A(object):
... def __del__(self):
... print(self.__dict__)
...
>>> a = A()
>>> b = A()
>>> a.b = b
>>>
{}
{'b': <__main__.A object at 0x7f3e85a5c6a0>}
(I pressed ^D
on that last interpreter line, triggering interpreter exit)
The first instance to be destroyed is b
(the one with no properties), the second is a
: that's the opposite of what references would suggest. A python 3 bug maybe ?
So, after bringing this up on #python@freenode, the general advice is that I should not rely on __del__
, but instead use a context-manager which would know about all USB instances (spawned from it, directly or indirectly), and which would destroy them in a reliable way on __exit__
.
I've started working in this direction (USBDevice will become a context manager), and should push that commit (along with a few unrelated) some time this week-end.
Could you test with the new with_USBContext branch and tell me if it fixes the issue for you ?
You will need to adapt your code a bit. To make up for it, you do not need any more to:
Do not hesitate to comment on the usability & clarity of resulting API.
Yup, cleans up and exits nicely now.
For the record, I've updated the gist with the changes made.
API Commentary: Seems solid, in the context of mostly mirroring the C API. I think some explicit documentation would be useful, in addition to the examples. Thanks for bringing the constant names in line with libusb. It would also make sense to have a context manager associated with detaching/attaching the kernel driver.
Thanks for testing, this change is now released as part of version 1.5.0, uploaded to pypi.
About documentation, although I am not too happy with the current documentation I'm also not sure of the form it should take and what to put in it. I like pydoc, and tried to put informative docstrings to all public API. I am worried by documentation rot if it gets any further away from the actual code (I only updated the examples in README in my last pre-upload amend), and also try to not duplicate libusb's documentation. Any idea is welcome.
Porting over this script was pretty straightforward. I figured a section in the README about how it differs and additional Pythonisms would be good.
While tracking down an issue in another project, I wrote this script and found that it hangs in
libusb_unlock_events()
(called fromlibusb_close()
).I'm running Arch Linux current.
The C program I based this script on does not hang, but probably does things slightly different.