Index: kernel/generic/include/udebug/udebug.h
===================================================================
--- kernel/generic/include/udebug/udebug.h	(revision 7e6c9eb1727ba6de8775beb4d6c6ac964c1ddcdb)
+++ kernel/generic/include/udebug/udebug.h	(revision 0aa1665b932e64c1786b7cc2ee1964f9694cfd8b)
@@ -195,5 +195,5 @@
     bool end_variant);
 
-void udebug_thread_b_event(struct thread *t);
+void udebug_thread_b_event_attach(struct thread *t, struct task *ta);
 void udebug_thread_e_event(void);
 
Index: kernel/generic/src/proc/thread.c
===================================================================
--- kernel/generic/src/proc/thread.c	(revision 7e6c9eb1727ba6de8775beb4d6c6ac964c1ddcdb)
+++ kernel/generic/src/proc/thread.c	(revision 0aa1665b932e64c1786b7cc2ee1964f9694cfd8b)
@@ -764,11 +764,17 @@
 			 }
 		}
+#ifdef CONFIG_UDEBUG
+		/*
+		 * Generate udebug THREAD_B event and attach the thread.
+		 * This must be done atomically (with the debug locks held),
+		 * otherwise we would either miss some thread or receive
+		 * THREAD_B events for threads that already existed
+		 * and could be detected with THREAD_READ before.
+		 */
+		udebug_thread_b_event_attach(t, TASK);
+#else
 		thread_attach(t, TASK);
+#endif
 		thread_ready(t);
-
-#ifdef CONFIG_UDEBUG
-		/* Generate udebug THREAD_B event */
-		udebug_thread_b_event(t);
-#endif
 
 		return 0;
Index: kernel/generic/src/udebug/udebug.c
===================================================================
--- kernel/generic/src/udebug/udebug.c	(revision 7e6c9eb1727ba6de8775beb4d6c6ac964c1ddcdb)
+++ kernel/generic/src/udebug/udebug.c	(revision 0aa1665b932e64c1786b7cc2ee1964f9694cfd8b)
@@ -306,13 +306,21 @@
 }
 
-/** Thread-creation event hook.
+/** Thread-creation event hook combined with attaching the thread.
  *
  * Must be called when a new userspace thread is created in the debugged
- * task. Generates a THREAD_B event.
+ * task. Generates a THREAD_B event. Also attaches the thread @a t
+ * to the task @a ta.
+ *
+ * This is necessary to avoid a race condition where the BEGIN and THREAD_READ
+ * requests would be handled inbetween attaching the thread and checking it
+ * for being in a debugging session to send the THREAD_B event. We could then
+ * either miss threads or get some threads both in the thread list
+ * and get a THREAD_B event for them.
  *
  * @param t	Structure of the thread being created. Not locked, as the
  *		thread is not executing yet.
- */
-void udebug_thread_b_event(struct thread *t)
+ * @param ta	Task to which the thread should be attached.
+ */
+void udebug_thread_b_event_attach(struct thread *t, struct task *ta)
 {
 	call_t *call;
@@ -320,4 +328,6 @@
 	mutex_lock(&TASK->udebug.lock);
 	mutex_lock(&THREAD->udebug.lock);
+
+	thread_attach(t, ta);
 
 	LOG("udebug_thread_b_event\n");
