diff -Nur linux.old/drivers/usb/hub.c linux.new/drivers/usb/hub.c
--- linux.old/drivers/usb/hub.c	Mon Nov 12 18:34:16 2001
+++ linux.new/drivers/usb/hub.c	Sun Mar 17 10:45:09 2002
@@ -7,6 +7,9 @@
  * (C) Copyright 2001 Brad Hards (bhards@bigpond.net.au)
  *
  */
+/* Workaround to avoid zombies. (Untested)
+ * (C) 2001 Kasper Dupont <kasperd@daimi.au.dk>
+ */
 
 #include <linux/config.h>
 #include <linux/kernel.h>
@@ -702,7 +705,7 @@
 		kfree(tempstr);
 }
 
-static void usb_hub_events(void)
+static void usb_hub_events(void*unused)
 {
 	unsigned long flags;
 	struct list_head *tmp;
@@ -840,7 +843,22 @@
 
 	/* Send me a signal to get me die (for debugging) */
 	do {
-		usb_hub_events();
+		/* Instead of calling usb_hub_events()
+		 * I leave the job to keventd. That way
+		 * new kernel threads will have keventd
+		 * as father instead of khubd. It would
+		 * be better but more difficult to have
+		 * khubd taking care of its own dead
+		 * children.
+		 */
+		struct tq_struct task;
+		task.routine=usb_hub_events;
+		schedule_task(&task);
+		/* I believe flushing at this point is
+		 * the safest thing to do. It might not
+		 * be the most efficient though.
+		 */
+		flush_scheduled_tasks();
 		interruptible_sleep_on(&khubd_wait);
 	} while (!signal_pending(current));
 
