return NULL;
r = usbi_mutex_init(&dev->lock, NULL);
- if (r)
+ if (r) {
+ free(dev);
return NULL;
+ }
dev->ctx = ctx;
dev->refcnt = 1;
return LIBUSB_ERROR_NO_MEM;
r = usbi_mutex_init(&_handle->lock, NULL);
- if (r)
+ if (r) {
+ free(_handle);
return LIBUSB_ERROR_OTHER;
+ }
_handle->dev = libusb_ref_device(dev);
_handle->claimed_interfaces = 0;
r = usbi_backend->open(_handle);
if (r < 0) {
libusb_unref_device(dev);
+ usbi_mutex_destroy(&_handle->lock);
free(_handle);
return r;
}
usbi_backend->close(dev_handle);
libusb_unref_device(dev_handle->dev);
+ usbi_mutex_destroy(&dev_handle->lock);
free(dev_handle);
}
return 0;
err:
+ usbi_mutex_destroy(&ctx->open_devs_lock);
+ usbi_mutex_destroy(&ctx->usb_devs_lock);
free(ctx);
return r;
}
}
usbi_mutex_static_unlock(&default_context_lock);
+ usbi_mutex_destroy(&ctx->open_devs_lock);
+ usbi_mutex_destroy(&ctx->usb_devs_lock);
free(ctx);
}
/* FIXME should use an eventfd on kernels that support it */
r = pipe(ctx->ctrl_pipe);
- if (r < 0)
- return LIBUSB_ERROR_OTHER;
+ if (r < 0) {
+ r = LIBUSB_ERROR_OTHER;
+ goto err;
+ }
r = usbi_add_pollfd(ctx, ctx->ctrl_pipe[0], POLLIN);
if (r < 0)
- return r;
+ goto err_close_pipe;
#ifdef USBI_TIMERFD_AVAILABLE
ctx->timerfd = timerfd_create(usbi_backend->get_timerfd_clockid(),
r = usbi_add_pollfd(ctx, ctx->timerfd, POLLIN);
if (r < 0) {
close(ctx->timerfd);
- return r;
+ goto err_close_pipe;
}
} else {
usbi_dbg("timerfd not available (code %d error %d)", ctx->timerfd, errno);
#endif
return 0;
+
+err_close_pipe:
+ close(ctx->ctrl_pipe[0]);
+ close(ctx->ctrl_pipe[1]);
+err:
+ usbi_mutex_destroy(&ctx->flying_transfers_lock);
+ usbi_mutex_destroy(&ctx->pollfds_lock);
+ usbi_mutex_destroy(&ctx->pollfd_modify_lock);
+ usbi_mutex_destroy(&ctx->events_lock);
+ usbi_mutex_destroy(&ctx->event_waiters_lock);
+ usbi_cond_destroy(&ctx->event_waiters_cond);
+ return r;
}
void usbi_io_exit(struct libusb_context *ctx)
close(ctx->timerfd);
}
#endif
+ usbi_mutex_destroy(&ctx->flying_transfers_lock);
+ usbi_mutex_destroy(&ctx->pollfds_lock);
+ usbi_mutex_destroy(&ctx->pollfd_modify_lock);
+ usbi_mutex_destroy(&ctx->events_lock);
+ usbi_mutex_destroy(&ctx->event_waiters_lock);
+ usbi_cond_destroy(&ctx->event_waiters_cond);
}
static int calculate_timeout(struct usbi_transfer *transfer)
/* TODO: malloc when number of fd's changes, not on every poll */
fds = malloc(sizeof(*fds) * nfds);
- if (!fds)
+ if (!fds) {
+ usbi_mutex_unlock(&ctx->pollfds_lock);
return LIBUSB_ERROR_NO_MEM;
+ }
list_for_each_entry(ipollfd, &ctx->pollfds, list) {
struct libusb_pollfd *pollfd = &ipollfd->pollfd;