⬢ DragonFlyBSD Kernel Audit
DF-2850 / fix.diff
← back to finding ↓ download raw
--- sys/kern/subr_gtaskqueue.c	2026-06-29 12:51:19.000000000 +0000
+++ /tmp/opencode/v26/fixtree/sys/kern/subr_gtaskqueue.c	2026-10-24 16:33:07.789715562 +0000
@@ -70,6 +70,7 @@
 	struct thread		**tq_threads;
 	int			tq_tcount;
 	int			tq_flags;
+	int			tq_first_error;	/* DF-2850 */
 #if 0
 	taskqueue_callback_fn	tq_callbacks[TASKQUEUE_NUM_CALLBACKS];
 	void			*tq_cb_contexts[TASKQUEUE_NUM_CALLBACKS];
@@ -453,13 +454,26 @@
 					    "%s_%d", ktname, i);
 		}
 		if (error) {
-			/* should be ok to continue, taskqueue_free will dtrt */
+			/*
+			 * DF-2850: remember the failure; if NO thread was
+			 * created the queue can never run anything and
+			 * every future drain would sleep forever - tear
+			 * the partial state down and report the error
+			 * instead of silently returning success.
+			 */
 			kprintf("%s: lwkt_create(%s): error %d",
 				__func__, ktname, error);
-			tq->tq_threads[i] = NULL;		/* paranoid */
+			tq->tq_threads[i] = NULL;
+			if (tq->tq_first_error == 0)
+				tq->tq_first_error = error;
 		} else
 			tq->tq_tcount++;
 	}
+	if (tq->tq_tcount == 0 && tq->tq_first_error) {
+		kfree(tq->tq_threads, M_GTASKQUEUE);
+		tq->tq_threads = NULL;
+		return (tq->tq_first_error);
+	}
 	for (i = 0; i < count; i++) {
 		if (tq->tq_threads[i] == NULL)
 			continue;