about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog5
-rw-r--r--sysdeps/mach/hurd/fork.c32
2 files changed, 29 insertions, 8 deletions
diff --git a/ChangeLog b/ChangeLog
index 5d65725244..dd1dd7781a 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+2002-09-19  Neal H. Walfield  <neal@cs.uml.edu>
+
+	* sysdeps/mach/hurd/fork.c (__fork): Do not free the signal
+	thread's sigstate data structure if it has been allocated.
+
 2002-09-19  Roland McGrath  <roland@redhat.com>
 
 	* include/libc-symbols.h [HAVE_ASM_SET_DIRECTIVE]
diff --git a/sysdeps/mach/hurd/fork.c b/sysdeps/mach/hurd/fork.c
index c5dee0cdad..b64a83d766 100644
--- a/sysdeps/mach/hurd/fork.c
+++ b/sysdeps/mach/hurd/fork.c
@@ -609,14 +609,17 @@ __fork (void)
       for (i = 0; i < _hurd_nports; ++i)
 	__spin_unlock (&_hurd_ports[i].lock);
 
-      /* We are the only thread in this new task, so we will
-	 take the task-global signals.  */
+      /* We are one of the (exactly) two threads in this new task, we
+	 will take the task-global signals.  */
       _hurd_sigthread = ss->thread;
 
-      /* Unchain the sigstate structures for threads that existed in the
-	 parent task but don't exist in this task (the child process).
-	 Delay freeing them until later because some of the further setup
-	 and unlocking might be required for free to work.  */
+      /* Claim our sigstate structure and unchain the rest: the
+	 threads existed in the parent task but don't exist in this
+	 task (the child process).  Delay freeing them until later
+	 because some of the further setup and unlocking might be
+	 required for free to work.  Before we finish cleaning up,
+	 we will reclaim the signal thread's sigstate structure (if
+	 it had one).  */
       oldstates = _hurd_sigstates;
       if (oldstates == ss)
 	oldstates = ss->next;
@@ -650,13 +653,26 @@ __fork (void)
       if (!err)
 	err = __thread_resume (_hurd_msgport_thread);
 
-      /* Free the old sigstate structures.  */
+      /* Reclaim the signal thread's sigstate structure and free the
+	 other old sigstate structures.  */
       while (oldstates != NULL)
 	{
 	  struct hurd_sigstate *next = oldstates->next;
-	  free (oldstates);
+
+	  if (oldstates->thread == _hurd_msgport_thread)
+	    {
+	      /* If we have a second signal state structure then we
+		 must have been through here before--not good.  */
+	      assert (_hurd_sigstates->next == 0);
+	      _hurd_sigstates->next = oldstates;
+	      oldstates->next = 0;
+	    }
+	  else
+	    free (oldstates);
+
 	  oldstates = next;
 	}
+
       /* XXX what to do if we have any errors here? */
 
       pid = 0;