Symptom
txdemo on a Jaguar1 chip (observed on the RTL8814AU, 0bda:8813) segfaults on teardown when terminated during max-duty TX (DEVOURER_TX_GAP_US=0). 3/3 bench cells crashed on timeout-driven SIGTERM; a manual kill -TERM reproduces deterministically at gap 0 and exits cleanly at gap 2000. Zero effect on measurements (crash is post-measurement, exit path only).
Backtrace (gdb attach, current master)
#0 ?? () from libusb-1.0.so.0
#2 libusb_handle_events_timeout_completed ()
#3 devourer::UsbTransport::~UsbTransport()
#6 _Sp_counted_ptr_inplace<devourer::UsbTransport>::_M_dispose()
#11 RtlAdapter::~RtlAdapter()
#12 EepromManager::~EepromManager()
Analysis
Teardown-order bug. EepromManager's RtlAdapter copy holds (what is at that point) the last shared_ptr<IRtlTransport> reference, so ~UsbTransport runs from inside ~EepromManager — i.e. mid-way through the device object's member destruction, while the Jaguar1 async TX pipeline still has in-flight URBs (gap-0 keeps it full at exit). The destructor's libusb_handle_events pump then dispatches completion callbacks whose state (or the transport itself) is already partially destroyed → SEGV inside libusb.
Consistent with the trigger profile:
- gap 0 (async queue saturated at TERM) → crash
- gap 2000 (queue drains between frames) → clean exit
Repro
DEVOURER_PID=0x8813 DEVOURER_CHANNEL=36 DEVOURER_TX_RATE=MCS7 DEVOURER_TX_GAP_US=0 build/txdemo &
sleep 8; kill -TERM %1 # SIGSEGV
# gap 2000 instead -> exits normally
Fix direction
Cancel/drain the async TX pipeline (the #252 caller-thread reaping machinery) before transport destruction — e.g. an explicit shutdown that cancels in-flight transfers and reaps them while all owners are still alive, rather than relying on shared_ptr teardown order; or ensure the device's destructor quiesces TX before members (EepromManager et al.) release their adapter copies.
Found while re-benchmarking the 8814AU README row (#110 re-validation session).
Symptom
txdemoon a Jaguar1 chip (observed on the RTL8814AU,0bda:8813) segfaults on teardown when terminated during max-duty TX (DEVOURER_TX_GAP_US=0). 3/3 bench cells crashed ontimeout-driven SIGTERM; a manualkill -TERMreproduces deterministically at gap 0 and exits cleanly at gap 2000. Zero effect on measurements (crash is post-measurement, exit path only).Backtrace (gdb attach, current master)
Analysis
Teardown-order bug.
EepromManager'sRtlAdaptercopy holds (what is at that point) the lastshared_ptr<IRtlTransport>reference, so~UsbTransportruns from inside~EepromManager— i.e. mid-way through the device object's member destruction, while the Jaguar1 async TX pipeline still has in-flight URBs (gap-0 keeps it full at exit). The destructor'slibusb_handle_eventspump then dispatches completion callbacks whose state (or the transport itself) is already partially destroyed → SEGV inside libusb.Consistent with the trigger profile:
Repro
Fix direction
Cancel/drain the async TX pipeline (the #252 caller-thread reaping machinery) before transport destruction — e.g. an explicit shutdown that cancels in-flight transfers and reaps them while all owners are still alive, rather than relying on shared_ptr teardown order; or ensure the device's destructor quiesces TX before members (EepromManager et al.) release their adapter copies.
Found while re-benchmarking the 8814AU README row (#110 re-validation session).