core: really fix dangling devices

The prior fix made an incorrect assumption about the reference counting of
parent devices. This CL fixes the issue by checking if the parent device
should be removed from the list as well. This is needed as when the child
device is released the parent may also be released.

Closes #924

Signed-off-by: Nathan Hjelm <hjelmn@google.com>
diff --git a/libusb/hotplug.c b/libusb/hotplug.c
index b6f896a..52ce626 100644
--- a/libusb/hotplug.c
+++ b/libusb/hotplug.c
@@ -166,7 +166,6 @@
 	struct usbi_hotplug_callback *hotplug_cb, *next_cb;
 	struct usbi_hotplug_message *msg;
 	struct libusb_device *dev, *next_dev;
-	int devices_released;
 
 	/* check for hotplug support */
 	if (!libusb_has_capability(LIBUSB_CAP_HAS_HOTPLUG))
@@ -192,19 +191,22 @@
 	}
 
 	/* free all discovered devices. due to parent references loop until no devices are freed. */
-	do {
-		devices_released = 0;
-		for_each_device_safe(ctx, dev, next_dev) {
-			/* remove the device from the usb_devs list only if there are no
-			 * references held, otherwise leave it on the list so that a
-			 * warning message will be shown */
-			if (usbi_atomic_load(&dev->refcnt) == 1) {
-				++devices_released;
-				list_del(&dev->list);
-			}
-			libusb_unref_device(dev);
+	for_each_device_safe(ctx, dev, next_dev) {
+		/* remove the device from the usb_devs list only if there are no
+		 * references held, otherwise leave it on the list so that a
+		 * warning message will be shown */
+		if (usbi_atomic_load(&dev->refcnt) == 1) {
+			list_del(&dev->list);
 		}
-	} while (devices_released > 0);
+		if (dev->parent_dev && usbi_atomic_load(&dev->parent_dev->refcnt) == 1) {
+			/* the parent was before this device in the list and will be released.
+			   remove it from the list. this is safe as parent_dev can not be
+			   equal to next_dev. */
+			assert (dev->parent_dev != next_dev);
+			list_del(&dev->parent_dev->list);
+		}
+		libusb_unref_device(dev);
+	}
 
 	usbi_mutex_destroy(&ctx->hotplug_cbs_lock);
 }
diff --git a/libusb/version_nano.h b/libusb/version_nano.h
index 043064c..b5bcf19 100644
--- a/libusb/version_nano.h
+++ b/libusb/version_nano.h
@@ -1 +1 @@
-#define LIBUSB_NANO 11627
+#define LIBUSB_NANO 11628