summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNiklas Gürtler <niklas.guertler@tacterion.com>2023-04-03 16:00:37 +0200
committerNathan Hjelm <hjelmn@google.com>2023-04-12 13:06:57 -0600
commitc5aec6bd678cddfab87df35de2c133f51bc8cce9 (patch)
tree52734d1052e71aa75a1b88a20824a3fd652044a4
parent84ac0b0f60323fab7ae765b2119df6149968b6e2 (diff)
downloadlibusb-c5aec6bd678cddfab87df35de2c133f51bc8cce9.tar.gz
Fix #1263 by acquiring the waiters lock while calling transfer callbacks and swapping the order of operations in sync_transfer_cb
Fixes #1267, #1263 Signed-off-by: Nathan Hjelm <hjelmn@google.com>
-rw-r--r--libusb/io.c5
-rw-r--r--libusb/sync.c9
-rw-r--r--libusb/version_nano.h2
3 files changed, 12 insertions, 4 deletions
diff --git a/libusb/io.c b/libusb/io.c
index 7c20a7e..36e0b81 100644
--- a/libusb/io.c
+++ b/libusb/io.c
@@ -1719,8 +1719,11 @@ int usbi_handle_transfer_completion(struct usbi_transfer *itransfer,
transfer->actual_length = itransfer->transferred;
usbi_dbg(ctx, "transfer %p has callback %p",
(void *) transfer, transfer->callback);
- if (transfer->callback)
+ if (transfer->callback) {
+ libusb_lock_event_waiters (ctx);
transfer->callback(transfer);
+ libusb_unlock_event_waiters(ctx);
+ }
/* transfer might have been freed by the above call, do not use from
* this point. */
if (flags & LIBUSB_TRANSFER_FREE_TRANSFER)
diff --git a/libusb/sync.c b/libusb/sync.c
index 27b5951..146cce2 100644
--- a/libusb/sync.c
+++ b/libusb/sync.c
@@ -34,10 +34,15 @@
static void LIBUSB_CALL sync_transfer_cb(struct libusb_transfer *transfer)
{
+ usbi_dbg(TRANSFER_CTX(transfer), "actual_length=%d", transfer->actual_length);
+
int *completed = transfer->user_data;
*completed = 1;
- usbi_dbg(TRANSFER_CTX(transfer), "actual_length=%d", transfer->actual_length);
- /* caller interprets result and frees transfer */
+ /*
+ * Right after setting 'completed', another thread might free the transfer, so don't
+ * access it beyond this point. The instantiating thread (not necessarily the
+ * current one) interprets the result and frees the transfer.
+ */
}
static void sync_transfer_wait_for_completion(struct libusb_transfer *transfer)
diff --git a/libusb/version_nano.h b/libusb/version_nano.h
index cb1eb95..ea168c3 100644
--- a/libusb/version_nano.h
+++ b/libusb/version_nano.h
@@ -1 +1 @@
-#define LIBUSB_NANO 11792
+#define LIBUSB_NANO 11793