}
/*
- * Interrupt the iteration of the event handling thread, so that it picks
- * up the new fd.
+ * Signal the event pipe so that the event handling thread will be
+ * interrupted to process an internal event.
*/
-void usbi_fd_notification(struct libusb_context *ctx)
+int usbi_signal_event(struct libusb_context *ctx)
{
unsigned char dummy = 1;
ssize_t r;
/* write some data on event pipe to interrupt event handlers */
r = usbi_write(ctx->event_pipe[1], &dummy, sizeof(dummy));
- if (r != sizeof(dummy))
+ if (r != sizeof(dummy)) {
usbi_warn(ctx, "internal signalling write failed");
+ return LIBUSB_ERROR_IO;
+ }
+
+ return 0;
+}
+
+/*
+ * Clear the event pipe so that the event handling will no longer be
+ * interrupted.
+ */
+int usbi_clear_event(struct libusb_context *ctx)
+{
+ unsigned char dummy;
+ ssize_t r;
+
+ /* read some data on event pipe to clear it */
+ r = usbi_read(ctx->event_pipe[0], &dummy, sizeof(dummy));
+ if (r != sizeof(dummy)) {
+ usbi_warn(ctx, "internal signalling read failed");
+ return LIBUSB_ERROR_IO;
+ }
+
+ return 0;
+}
+
+/*
+ * Interrupt the iteration of the event handling thread, so that it picks
+ * up the new fd.
+ */
+void usbi_fd_notification(struct libusb_context *ctx)
+{
+ usbi_signal_event(ctx);
}
/** \ingroup dev
void API_EXPORTED libusb_close(libusb_device_handle *dev_handle)
{
struct libusb_context *ctx;
- unsigned char dummy = 1;
- ssize_t r;
if (!dev_handle)
return;
ctx->device_close++;
usbi_mutex_unlock(&ctx->event_data_lock);
- /* write some data on event pipe to interrupt event handlers */
- r = usbi_write(ctx->event_pipe[1], &dummy, sizeof(dummy));
- if (r <= 0) {
- usbi_warn(ctx, "internal signalling write failed, closing anyway");
- do_close(ctx, dev_handle);
- usbi_mutex_lock(&ctx->event_data_lock);
- ctx->device_close--;
- usbi_mutex_unlock(&ctx->event_data_lock);
- return;
- }
+ /* signal the event pipe to interrupt event handlers */
+ usbi_signal_event(ctx);
/* take event handling lock */
libusb_lock_events(ctx);
- /* read the dummy data */
- r = usbi_read(ctx->event_pipe[0], &dummy, sizeof(dummy));
- if (r <= 0)
- usbi_warn(ctx, "internal signalling read failed, closing anyway");
+ /* clear the event pipe */
+ usbi_clear_event(ctx);
/* Close the device */
do_close(ctx, dev_handle);
/* another thread wanted to interrupt event handling, and it succeeded!
* handle any other events that cropped up at the same time, and
* simply return */
- ssize_t ret;
- unsigned char dummy;
unsigned int ru;
usbi_dbg("caught a fish on the event pipe");
ru = ctx->device_close;
usbi_mutex_unlock(&ctx->event_data_lock);
if (!ru) {
- ret = usbi_read(ctx->event_pipe[0], &dummy, sizeof(dummy));
- if (ret != sizeof(dummy)) {
- usbi_err(ctx, "event pipe read error %d err=%d",
- ret, errno);
- r = LIBUSB_ERROR_OTHER;
+ r = usbi_clear_event(ctx);
+ if (r)
goto handled;
- }
}
if (0 == --r)