]> www.infradead.org Git - users/borneoa/openocd-next.git/commitdiff
cmsis-dap: Fix freeing pending transfers on close
authorkryvosheiaivan <Ivan.Kryvosheia@infineon.com>
Wed, 28 May 2025 13:52:42 +0000 (16:52 +0300)
committerAntonio Borneo <borneo.antonio@gmail.com>
Fri, 13 Jun 2025 16:27:37 +0000 (16:27 +0000)
Freeing pending transfers on shutdown is done in openOCD
and on libusb side. This created concurrency in freeing
memory and segmentation faults:
https://github.com/libusb/libusb/issues/1627
Bug is reproduced better if many targets are laucnhed.
Bug was reproduced with CMSIS-DAP on targets:
cyw20829, psoc4, stm32l5 if launching multiple times.
Proposed working fix: if some transfers pending/in-flight
on 'shutdown' then apply libusb_handle_events_timeout_completed()
to make transfer complete. In all cases transfer completed
due to tests.

Change-Id: I44621ac6096791714910220d04614d0a19ce47bd
Signed-off-by: kryvosheiaivan <Ivan.Kryvosheia@infineon.com>
Reviewed-on: https://review.openocd.org/c/openocd/+/8876
Reviewed-by: Tomas Vanek <vanekt@fbl.cz>
Tested-by: jenkins
Reviewed-by: Antonio Borneo <borneo.antonio@gmail.com>
src/jtag/drivers/cmsis_dap_usb_bulk.c

index 8fbcb029dd8eb457e3a54142e9580389458afd62..0dd6b2bbceb77e4896ef57db6f18ccdef3c2116f 100644 (file)
@@ -414,7 +414,19 @@ static int cmsis_dap_usb_open(struct cmsis_dap *dap, uint16_t vids[], uint16_t p
 static void cmsis_dap_usb_close(struct cmsis_dap *dap)
 {
        for (unsigned int i = 0; i < MAX_PENDING_REQUESTS; i++) {
-               libusb_free_transfer(dap->bdata->command_transfers[i].transfer);
+               if (dap->bdata->command_transfers[i].status == CMSIS_DAP_TRANSFER_PENDING) {
+                       LOG_DEBUG("busy command USB transfer at %u", dap->pending_fifo_put_idx);
+                       struct timeval tv = {
+                               .tv_sec = 1,
+                               .tv_usec = 1000
+                       };
+                       /* Complete pending commands */
+                       int res = libusb_handle_events_timeout_completed(dap->bdata->usb_ctx, &tv, NULL);
+                       if (res == 0)
+                               libusb_free_transfer(dap->bdata->command_transfers[i].transfer);
+               } else {
+                       libusb_free_transfer(dap->bdata->command_transfers[i].transfer);
+               }
                libusb_free_transfer(dap->bdata->response_transfers[i].transfer);
        }
        cmsis_dap_usb_free(dap);