summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Dickens <christopher.a.dickens@gmail.com>2020-08-18 09:19:03 -0700
committerChris Dickens <christopher.a.dickens@gmail.com>2020-08-18 09:19:03 -0700
commit37e8b1334e59485e1d4735f5f67b31eba37ae5c9 (patch)
treec5c77139bf226ae7bf4f1d67a891f8eef61b026d
parentd42410b21c4314143f31fd7f8494dd1d4c279663 (diff)
downloadlibusb-37e8b1334e59485e1d4735f5f67b31eba37ae5c9.tar.gz
Windows: Fix I/O completion port thread behavior on error
The GetQueuedCompletionStatus() returns FALSE when the I/O operation itself does not complete successfully. The I/O completion thread should therefore not exit on this condition. Adjust the check to verify that an OVERLAPPED structure was provided and use an explicit completion key value in the exit path to disambiguate receiving a valid NULL OVERLAPPED pointer. Signed-off-by: Chris Dickens <christopher.a.dickens@gmail.com>
-rw-r--r--libusb/os/windows_common.c13
-rw-r--r--libusb/version_nano.h2
2 files changed, 10 insertions, 5 deletions
diff --git a/libusb/os/windows_common.c b/libusb/os/windows_common.c
index 9406632..2f79928 100644
--- a/libusb/os/windows_common.c
+++ b/libusb/os/windows_common.c
@@ -418,13 +418,18 @@ static unsigned __stdcall windows_iocp_thread(void *arg)
usbi_dbg("I/O completion thread started");
while (true) {
- if (!GetQueuedCompletionStatus(iocp, &num_bytes, &completion_key, &overlapped, INFINITE)) {
+ overlapped = NULL;
+ if (!GetQueuedCompletionStatus(iocp, &num_bytes, &completion_key, &overlapped, INFINITE) && (overlapped == NULL)) {
usbi_err(ctx, "GetQueuedCompletionStatus failed: %s", windows_error_str(0));
break;
}
- if (overlapped == NULL)
- break; // Signal to quit
+ if (overlapped == NULL) {
+ // Signal to quit
+ if (completion_key != (ULONG_PTR)ctx)
+ usbi_err(ctx, "program assertion failed - overlapped is NULL");
+ break;
+ }
transfer_priv = container_of(overlapped, struct windows_transfer_priv, overlapped);
itransfer = (struct usbi_transfer *)((unsigned char *)transfer_priv + PTR_ALIGN(sizeof(*transfer_priv)));
@@ -556,7 +561,7 @@ static void windows_exit(struct libusb_context *ctx)
}
// A NULL completion status will indicate to the thread that it is time to exit
- if (!PostQueuedCompletionStatus(priv->completion_port, 0, 0, NULL))
+ if (!PostQueuedCompletionStatus(priv->completion_port, 0, (ULONG_PTR)ctx, NULL))
usbi_err(ctx, "failed to post I/O completion: %s", windows_error_str(0));
if (WaitForSingleObject(priv->completion_port_thread, INFINITE) == WAIT_FAILED)
diff --git a/libusb/version_nano.h b/libusb/version_nano.h
index bee4117..dfaf221 100644
--- a/libusb/version_nano.h
+++ b/libusb/version_nano.h
@@ -1 +1 @@
-#define LIBUSB_NANO 11537
+#define LIBUSB_NANO 11538