Navigation Menu

Skip to content

Commit

Permalink
core: release the context device list when the context is deleted.
Browse files Browse the repository at this point in the history
This commit fixes a memory leak in the context list patch. Devices need
to be unref'd when the context is deleted. This can happen if either 1)
the backend init fails, or 2) the context is destroyed by libusb_exit().
  • Loading branch information
hjelmn committed Apr 26, 2013
1 parent 1c1d686 commit e63fb62
Showing 1 changed file with 26 additions and 10 deletions.
36 changes: 26 additions & 10 deletions libusb/core.c
Expand Up @@ -1668,6 +1668,7 @@ void API_EXPORTED libusb_set_debug(libusb_context *ctx, int level)
*/
int API_EXPORTED libusb_init(libusb_context **context)
{
struct libusb_device *dev, *next;
char *dbg = getenv("LIBUSB_DEBUG");
struct libusb_context *ctx;
static int first_init = 1;
Expand Down Expand Up @@ -1731,21 +1732,27 @@ int API_EXPORTED libusb_init(libusb_context **context)
}
usbi_mutex_static_unlock(&default_context_lock);

usbi_mutex_static_lock(&active_contexts_lock);
if (first_init) {
first_init = 0;
list_init (&active_contexts_list);
}
usbi_mutex_static_lock(&active_contexts_lock);
if (first_init) {
first_init = 0;
list_init (&active_contexts_list);
}

list_add (&ctx->list, &active_contexts_list);
usbi_mutex_static_unlock(&active_contexts_lock);
list_add (&ctx->list, &active_contexts_list);
usbi_mutex_static_unlock(&active_contexts_lock);

return 0;

err_destroy_mutex:
usbi_mutex_destroy(&ctx->open_devs_lock);
usbi_mutex_destroy(&ctx->usb_devs_lock);
err_free_ctx:
usbi_mutex_lock(&ctx->usb_devs_lock);
list_for_each_entry_safe(dev, next, &ctx->usb_devs, list, struct libusb_device) {
list_del(&dev->list);
libusb_unref_device(dev);
}
usbi_mutex_unlock(&ctx->usb_devs_lock);
free(ctx);
err_unlock:
usbi_mutex_static_unlock(&default_context_lock);
Expand All @@ -1759,6 +1766,8 @@ int API_EXPORTED libusb_init(libusb_context **context)
*/
void API_EXPORTED libusb_exit(struct libusb_context *ctx)
{
struct libusb_device *dev, *next;

usbi_dbg("");
USBI_GET_CONTEXT(ctx);

Expand All @@ -1776,12 +1785,19 @@ void API_EXPORTED libusb_exit(struct libusb_context *ctx)
usbi_mutex_static_unlock(&default_context_lock);
}

usbi_mutex_static_lock(&active_contexts_lock);
list_del (&ctx->list);
usbi_mutex_static_unlock(&active_contexts_lock);
usbi_mutex_static_lock(&active_contexts_lock);
list_del (&ctx->list);
usbi_mutex_static_unlock(&active_contexts_lock);

usbi_hotplug_deregister_all(ctx);

usbi_mutex_lock(&ctx->usb_devs_lock);
list_for_each_entry_safe(dev, next, &ctx->usb_devs, list, struct libusb_device) {
list_del(&dev->list);
libusb_unref_device(dev);
}
usbi_mutex_unlock(&ctx->usb_devs_lock);

/* a little sanity check. doesn't bother with open_devs locking because
* unless there is an application bug, nobody will be accessing this. */
if (!list_empty(&ctx->open_devs))
Expand Down

0 comments on commit e63fb62

Please sign in to comment.