fix race condition at event_handles
authorFrank Li <Frank.Li@nxp.com>
Fri, 11 Jan 2019 17:56:47 +0000 (11:56 -0600)
committerNathan Hjelm <hjelmn@me.com>
Thu, 31 Jan 2019 05:38:32 +0000 (22:38 -0700)
event_handles supposed just run at a thread.

There are re-entry check at begin.

1: if (usbi_handling_events(ctx))
2: return LIBUSB_ERROR_BUSY;

3: usbi_stat_event_handle(ctx);

this code is hold any lock

it is possible two thread check 1 at the same time, then
go through to 3. So two threads will run event_handles.

above 3 line code should hold event_data_lock to avoid above
race condition.

1: usbi_mutex_lock($ctx->event_data_lock);
2: r = 0;
3: if (usbi_handling_events(ctx))
4:  r = LIBUSB_ERROR_BUSY;
5: else
6:  usbi_start_event_handling(ctx);
7: usbi_mutex_unlock($ctx->event_data_lock);

8: if(r)
9: return r;

check and set in an atomic operations.

Closes #520

Signed-off-by: Frank Li <Frank.Li@nxp.com>
Signed-off-by: Nathan Hjelm <hjelmn@me.com>
libusb/io.c
libusb/version_nano.h

index 8c2b02a..6051d7f 100644 (file)
@@ -2081,9 +2081,16 @@ static int handle_events(struct libusb_context *ctx, struct timeval *tv)
 
        /* prevent attempts to recursively handle events (e.g. calling into
         * libusb_handle_events() from within a hotplug or transfer callback) */
+       usbi_mutex_lock(&ctx->event_data_lock);
+       r = 0;
        if (usbi_handling_events(ctx))
-               return LIBUSB_ERROR_BUSY;
-       usbi_start_event_handling(ctx);
+               r = LIBUSB_ERROR_BUSY;
+       else
+               usbi_start_event_handling(ctx);
+       usbi_mutex_unlock(&ctx->event_data_lock);
+
+       if (r)
+               return r;
 
        /* there are certain fds that libusb uses internally, currently:
         *
index 6d522b6..da4558f 100644 (file)
@@ -1 +1 @@
-#define LIBUSB_NANO 11342
+#define LIBUSB_NANO 11343