about summary refs log tree commit diff
path: root/sysdeps/mach/hurd/fork.c
diff options
context:
space:
mode:
authorRoland McGrath <roland@gnu.org>2002-09-20 03:31:58 +0000
committerRoland McGrath <roland@gnu.org>2002-09-20 03:31:58 +0000
commit4ac9bb2e4a9c8be4c0f27ef7ede2bc7a9e219083 (patch)
tree9623636c75d05aa97c55066aa37ba1f64860baf6 /sysdeps/mach/hurd/fork.c
parent3c9117108e4bb02d66b454eee6ac6853efee78d5 (diff)
downloadglibc-4ac9bb2e4a9c8be4c0f27ef7ede2bc7a9e219083.tar.gz
glibc-4ac9bb2e4a9c8be4c0f27ef7ede2bc7a9e219083.tar.xz
glibc-4ac9bb2e4a9c8be4c0f27ef7ede2bc7a9e219083.zip
* sysdeps/mach/hurd/fork.c (__fork): Do not free the signal
	thread's sigstate data structure if it has been allocated.
Diffstat (limited to 'sysdeps/mach/hurd/fork.c')
-rw-r--r--sysdeps/mach/hurd/fork.c32
1 files changed, 24 insertions, 8 deletions
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;