about summary refs log tree commit diff
path: root/sysdeps/mach/hurd/fork.c
diff options
context:
space:
mode:
Diffstat (limited to 'sysdeps/mach/hurd/fork.c')
-rw-r--r--sysdeps/mach/hurd/fork.c22
1 files changed, 20 insertions, 2 deletions
diff --git a/sysdeps/mach/hurd/fork.c b/sysdeps/mach/hurd/fork.c
index 25279645ee..6fadb3d97d 100644
--- a/sysdeps/mach/hurd/fork.c
+++ b/sysdeps/mach/hurd/fork.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1994, 1995 Free Software Foundation, Inc.
+/* Copyright (C) 1994, 1995, 1996 Free Software Foundation, Inc.
 This file is part of the GNU C Library.
 
 The GNU C Library is free software; you can redistribute it and/or
@@ -121,7 +121,6 @@ __fork (void)
 	__spin_lock (&_hurd_ports[i].lock);
       ports_locked = 1;
 
-      *(volatile task_t *) &__mach_task_self_; /* XXX work around kernel bug */
 
       /* Stop all other threads while copying the address space,
 	 so nothing changes.  */
@@ -130,6 +129,25 @@ __fork (void)
         {
           stopped = 1;
 
+#define XXX_KERNEL_PAGE_FAULT_BUG /* XXX work around page fault bug in mk */
+
+#ifdef XXX_KERNEL_PAGE_FAULT_BUG
+	  /* Gag me with a pitchfork.
+	     The bug scenario is this:
+
+	     - The page containing __mach_task_self_ is paged out.
+	     - The signal thread was faulting on that page when we
+	       suspended it via proc_dostop.  It holds some lock, or set
+	       some busy bit, or somesuch.
+	     - Now this thread faults on that same page.
+	     - GRATUIOUS DEADLOCK
+
+	     We can break the deadlock by aborting the thread that faulted
+	     first, which if the bug happened was the signal thread because
+	     it is the only other thread and we just suspended it.
+	     */
+	  __thread_abort (_hurd_msgport_thread);
+#endif
 	  /* Create the child task.  It will inherit a copy of our memory.  */
 	  err = __task_create (__mach_task_self (), 1, &newtask);
         }