From 8046f2a38f8af0048c0d2d0842b8a708b79c0c57 Mon Sep 17 00:00:00 2001 From: kryvosheiaivan Date: Wed, 28 May 2025 16:52:42 +0300 Subject: [PATCH] cmsis-dap: Fix freeing pending transfers on close 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 Reviewed-on: https://review.openocd.org/c/openocd/+/8876 Reviewed-by: Tomas Vanek Tested-by: jenkins Reviewed-by: Antonio Borneo --- src/jtag/drivers/cmsis_dap_usb_bulk.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/jtag/drivers/cmsis_dap_usb_bulk.c b/src/jtag/drivers/cmsis_dap_usb_bulk.c index 8fbcb029d..0dd6b2bbc 100644 --- a/src/jtag/drivers/cmsis_dap_usb_bulk.c +++ b/src/jtag/drivers/cmsis_dap_usb_bulk.c @@ -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);