Fix a race condition with libusb_interrupt_event_handler().
authorLars Kanis <lars@greiz-reinsdorf.de>
Sun, 27 Nov 2016 16:41:01 +0000 (17:41 +0100)
committerHans de Goede <hdegoede@redhat.com>
Mon, 28 Nov 2016 08:25:33 +0000 (09:25 +0100)
USBI_EVENT_USER_INTERRUPT isn't set in case of another pending event. When
libusb_interrupt_event_handler() is called and USBI_EVENT_POLLFDS_MODIFIED is
already set, but libusb_handle_events() isn't currently active waiting in
poll(), the interrupt request will be cleared before poll() is called. poll()
therefore blocks and the event handler doesn't return.

This is especially the case, when libusb_interrupt_event_handler() is called
before the first call to libusb_handle_events(). In this case
libusb_handle_events() blocks instead of returning immediately.

This patch fixes the race condition by setting the event flag the same way a
usbi_fd_notification().

Signed-off-by: Lars Kanis <lars@greiz-reinsdorf.de>
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
libusb/io.c

index bf2b5fa..0026ba7 100644 (file)
@@ -1887,14 +1887,17 @@ int API_EXPORTED libusb_event_handler_active(libusb_context *ctx)
  */
 void API_EXPORTED libusb_interrupt_event_handler(libusb_context *ctx)
 {
+       int pending_events;
        USBI_GET_CONTEXT(ctx);
 
        usbi_dbg("");
        usbi_mutex_lock(&ctx->event_data_lock);
-       if (!usbi_pending_events(ctx)) {
-               ctx->event_flags |= USBI_EVENT_USER_INTERRUPT;
+
+       pending_events = usbi_pending_events(ctx);
+       ctx->event_flags |= USBI_EVENT_USER_INTERRUPT;
+       if (!pending_events)
                usbi_signal_event(ctx);
-       }
+
        usbi_mutex_unlock(&ctx->event_data_lock);
 }