commit 45afcc68979b700bdef1dc0e27ba79e0822b1c18
Author: Samuel Thibault <samuel.thibault@ens-lyon.org>
Date:   Sat Dec 3 20:18:36 2022 +0100

    task: Add task_set_essential
    
    Whenever a Hurd essential task crashes, startup just reboots the system
    since there's not much that can be done at that point. When we have a
    kernel debugger, however, we could at least get crashing information, so
    let's let Hurd's startup tell the kernel which tasks are essential, and
    trigger the debugger whenever they crash.

diff --git a/doc/mach.texi b/doc/mach.texi
index 4abafe1a..fecd097b 100644
--- a/doc/mach.texi
+++ b/doc/mach.texi
@@ -5100,6 +5100,17 @@ printed by the kernel.
 The function returns @code{KERN_SUCCESS} if the call succeeded.
 @end deftypefun
 
+@deftypefun kern_return_t task_set_essential (@w{task_t @var{target_task}}, @w{boolean_t @var{essential}})
+
+The function @code{task_set_essential} sets whether @var{target_task} is
+essential for the system, i.e. the system will completely crash and reboot if
+that task crashes. This means that when the debugger is enabled, it should be
+triggered on the crash, so as to get the opportunity to debug the issue instead
+of just rebooting.
+
+The function returns @code{KERN_SUCCESS} if the call succeeded.
+@end deftypefun
+
 
 @node Task Execution
 @subsection Task Execution
diff --git a/i386/i386/trap.c b/i386/i386/trap.c
index eef9432f..6e446ab0 100644
--- a/i386/i386/trap.c
+++ b/i386/i386/trap.c
@@ -565,11 +565,12 @@ int user_trap(struct i386_saved_state *regs)
 	}
 
 #if	MACH_TTD
-	if (debug_all_traps_with_kttd && kttd_trap(type, regs->err, regs))
+	if ((debug_all_traps_with_kttd || thread->task->essential) &&
+	    kttd_trap(type, regs->err, regs))
 		return 0;
 #endif	/* MACH_TTD */
 #if	MACH_KDB
-	if (debug_all_traps_with_kdb &&
+	if ((debug_all_traps_with_kdb || thread->task->essential) &&
 	    kdb_trap(type, regs->err, regs))
 		return 0;
 #endif	/* MACH_KDB */
diff --git a/include/mach/gnumach.defs b/include/mach/gnumach.defs
index 531b5d4d..05101a48 100644
--- a/include/mach/gnumach.defs
+++ b/include/mach/gnumach.defs
@@ -189,3 +189,11 @@ routine vm_allocate_contiguous(
 		pmin		: rpc_phys_addr_t;
 		pmax		: rpc_phys_addr_t;
 		palign		: rpc_phys_addr_t);
+
+/*
+ *	Set whether TASK is an essential task, i.e. the whole system will crash
+ *	if this task crashes.
+ */
+simpleroutine task_set_essential(
+		task	: task_t;
+		essential	: boolean_t);
diff --git a/kern/task.c b/kern/task.c
index e91c192b..e9158c73 100644
--- a/kern/task.c
+++ b/kern/task.c
@@ -178,6 +178,7 @@ task_create_kernel(
 
 	new_task->may_assign = TRUE;
 	new_task->assign_active = FALSE;
+	new_task->essential = FALSE;
 
 #if	MACH_PCSAMPLE
 	new_task->pc_sample.buffer = 0;
@@ -1156,6 +1157,21 @@ task_set_name(
 	return KERN_SUCCESS;
 }
 
+/*
+ *	task_set_essential
+ *
+ *	Set whether TASK is an essential task, i.e. the whole system will crash
+ *	if this task crashes.
+ */
+kern_return_t
+task_set_essential(
+	task_t			task,
+	boolean_t		essential)
+{
+	task->essential = !!essential;
+	return KERN_SUCCESS;
+}
+
 /*
  *	task_collect_scan:
  *
diff --git a/kern/task.h b/kern/task.h
index 52eb8324..6251317c 100644
--- a/kern/task.h
+++ b/kern/task.h
@@ -64,7 +64,8 @@ struct task {
 	/* Flags */
 	unsigned int	active:1,	/* Task has not been terminated */
 	/* boolean_t */ may_assign:1,	/* can assigned pset be changed? */
-			assign_active:1;	/* waiting for may_assign */
+			assign_active:1,	/* waiting for may_assign */
+			essential:1;	/* Is this task essential for the system? */
 
 	/* Miscellaneous */
 	vm_map_t	map;		/* Address space description */
