about summary refs log tree commit diff
path: root/sysdeps/mach
diff options
context:
space:
mode:
authorRoland McGrath <roland@gnu.org>1996-05-04 09:46:57 +0000
committerRoland McGrath <roland@gnu.org>1996-05-04 09:46:57 +0000
commit8f0c527e13b836a44fedbf6abc84e1901e2cc10d (patch)
tree2ef83b10742b3fa4e7dd89b7b55229ebf48c6818 /sysdeps/mach
parent7a12c6bba750ca500009854db3a0fcdfb1ad61a7 (diff)
downloadglibc-8f0c527e13b836a44fedbf6abc84e1901e2cc10d.tar.gz
glibc-8f0c527e13b836a44fedbf6abc84e1901e2cc10d.tar.xz
glibc-8f0c527e13b836a44fedbf6abc84e1901e2cc10d.zip
Sat May 4 05:44:25 1996 Roland McGrath <roland@delasyd.gnu.ai.mit.edu>
	* hurd/hurd-raise.c (_hurd_raise_signal): Pass sigcode in msg_sig_post
	rpc.

	* hurd/hurdmsg.c (_S_msg_set_environment): Use argz.h functions
	instead of _hurd_split_args.
	(_S_msg_*_exec_flags): Functions removed.
	(_S_msg_startup_dosync): Stub removed.

Sat May  4 02:11:55 1996  Roland McGrath  <roland@delasyd.gnu.ai.mit.edu>

	* sysdeps/mach/hurd/ptrace.c: Set _hurdsig_traced instead of
	EXEC_TRACED bit in _hurd_exec_flags.
	Pass sigcode arg in msg_sig_post_untraced rpc.

	* sysdeps/mach/hurd/access.c: Don't pass io port in
	auth_user_authenticate rpc.

	* posix/sched.h: Fix typos.

	* sysdeps/mach/hurd/fork.c: Use new critical section lock.
	Clear _hurdsig_traced instead of EXEC_TRACED.

	* sysdeps/stub/nanosleep.c (nanosleep): Fix typo.

	* wcsmbs/wcstol.c: Find strtol.c in ../stdlib.
	* wcsmbs/wcstof.c: Find strtod.c in ../stdlib.
	* wcsmbs/wcstod.c: Likewise.
	* wcsmbs/wcstold.c: Likewise.

	* wcsmbs/wcwidth.h: Find cname-lookup.h in ../wctype.

	* string/envz.c (envz_entry): Use const.
	(envz_get, envz_remove): Likewise.
	(envz_entry): Return char *, not const char *.

	* string/envz.h: Fix decl.

	* string/argz-create.c: Use const in prototype.
	* string/argz-next.c: Likewise.

	* sysdeps/mach/hurd/sigprocmask.c: Pass sigcode arg to msg_sig_post.
	* sysdeps/mach/hurd/i386/sigreturn.c: Likewise.
	* sysdeps/mach/hurd/sigsuspend.c: Likewise.
	* sysdeps/mach/hurd/kill.c: Likewise.

	* hurd/hurdexec.c (_hurd_exec): Use new critical section lock.
	* hurd/catch-exc.c (_S_catch_exception_raise): Likewise.
	* hurd/sigunwind.c (_hurdsig_longjmp_from_handler): Likewise.
	* hurd/thread-cancel.c (hurd_thread_cancel, hurd_check_cancel):
	Likewise.
	* sysdeps/mach/hurd/jmp-unwind.c (_longjmp_unwind): Likewise.
	* sysdeps/mach/hurd/sigaction.c: Likewise.

	* sysdeps/mach/hurd/errnos.awk: Don't use ARGV in comment; it can
	change meaninglessly.

	* hurd/hurd/signal.h (struct hurd_sigstate): Replace critical section
 	flag with a spin lock.
	(_hurd_critical_section_lock): Use spin_try_lock on that to see if we
 	get it.  No need to take SS->lock at all.
	(_hurd_critical_section_unlock): Unlock SS->critical_section_lock
	instead of clearing the old flag member.
	* hurd/hurdsig.c (_hurd_internal_post_signal): Use spin_lock_locked to
	test the critical section state.

	* hurd/hurdinit.c (_hurd_init): Set _hurdsig_traced from the intarray.

	* hurd/hurdkill.c (_hurd_sig_post): Pass 0 sigcode in msg_sig_post.

	* hurd/hurdsig.c (_hurd_internal_post_signal): Test _hurdsig_traced
 	instead of testing (_hurd_exec_flags & EXEC_TRACED).
	(_S_msg_sig_post): Take sigcode arg and pass it through.
	(_S_msg_sig_post_untraced): Likewise.
	(reauth_proc): Don't pass proc port in auth_user_authenticate.

	* hurd/setauth.c (_hurd_setauth): Don't pass object ports in
	auth_user_authenticate RPCs, just the one-off rendezvous port.
	* hurd/dtable.c (reauth_dtable): Likewise.
	* hurd/hurdlookup.c (__hurd_file_name_lookup_retry): Likewise.

	* hurd/hurdexec.c (_hurd_exec): Pass 0 flags to file_exec.
	Pass sigcode arg to msg_sig_post.

	* string/argz.h (argz_create): Use const in prototype.

	* hurd/hurdinit.c (_hurd_proc_init): Test _hurdsig_traced instead of
	testing (_hurd_exec_flags & EXEC_TRACED).
	Pass sigcode arg to msg_sig_post.

	* hurd/hurd.h: Declare _hurdsig_traced.

	* string/argz.h (__argz_next): Cast ENTRY before returning it.

	* hurd/hurd/signal.h (_hurd_critical_section_unlock): Pass sigcode arg
	to msg_sig_post.

	* hurd/path-lookup.c: New file.
	* hurd/Makefile (routines): Add path-lookup.
	* hurd/hurd/lookup.h: Declare file_name_path_scan,
	hurd_file_name_path_lookup.
	* hurd/hurd.h: Declare file_name_path_lookup.

	* sysdeps/mach/hurd/select.c: The io_select rpc no longer has a TAG_ID
	argument.  Instead, use a separate reply port for each RPC and put them
	all in a port set to wait for slow replies.
Diffstat (limited to 'sysdeps/mach')
-rw-r--r--sysdeps/mach/hurd/access.c5
-rw-r--r--sysdeps/mach/hurd/errnos.awk5
-rw-r--r--sysdeps/mach/hurd/errnos.h2
-rw-r--r--sysdeps/mach/hurd/fork.c6
-rw-r--r--sysdeps/mach/hurd/i386/sigreturn.c2
-rw-r--r--sysdeps/mach/hurd/jmp-unwind.c5
-rw-r--r--sysdeps/mach/hurd/kill.c2
-rw-r--r--sysdeps/mach/hurd/ptrace.c24
-rw-r--r--sysdeps/mach/hurd/select.c189
-rw-r--r--sysdeps/mach/hurd/sigaction.c8
-rw-r--r--sysdeps/mach/hurd/sigprocmask.c4
-rw-r--r--sysdeps/mach/hurd/sigsuspend.c8
12 files changed, 130 insertions, 130 deletions
diff --git a/sysdeps/mach/hurd/access.c b/sysdeps/mach/hurd/access.c
index 98e2bba3b0..eb57d92f27 100644
--- a/sysdeps/mach/hurd/access.c
+++ b/sysdeps/mach/hurd/access.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
+/* Copyright (C) 1991, 1992, 1993, 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
@@ -44,7 +44,6 @@ DEFUN(__access, (file, type), CONST char *file AND int type)
 	   err = __io_reauthenticate (port, ref, MACH_MSG_TYPE_MAKE_SEND);
 	   if (!err)
 	     err = __auth_user_authenticate (_hurd_id.rid_auth,
-					     port,
 					     ref, MACH_MSG_TYPE_MAKE_SEND,
 					     result);
 	   err;
@@ -106,7 +105,7 @@ DEFUN(__access, (file, type), CONST char *file AND int type)
 					    &_hurd_id.rid_auth)))
 	goto lose;
     }
-  
+
   if (!err)
     /* Look up the file name using the modified init ports.  */
     err = __hurd_file_name_lookup (&init_port, &__getdport,
diff --git a/sysdeps/mach/hurd/errnos.awk b/sysdeps/mach/hurd/errnos.awk
index 95cfe10da6..e3ff7a843b 100644
--- a/sysdeps/mach/hurd/errnos.awk
+++ b/sysdeps/mach/hurd/errnos.awk
@@ -23,10 +23,7 @@
 # @comment errno 123
 
 BEGIN {
-    printf "/* This file generated by";
-    for (i = 0; i < ARGC; ++i)
-      printf " %s", ARGV[i];
-    printf ".  */\n";
+    print "/* This file generated by errnos.awk.  */";
     print "";
     print "/* The Hurd uses Mach error system 0x10, currently only subsystem 0. */";
     print "#ifndef _HURD_ERRNO";
diff --git a/sysdeps/mach/hurd/errnos.h b/sysdeps/mach/hurd/errnos.h
index 31aa3104a5..2ec061596a 100644
--- a/sysdeps/mach/hurd/errnos.h
+++ b/sysdeps/mach/hurd/errnos.h
@@ -1,4 +1,4 @@
-/* This file generated by gawk ../manual/errno.texi ../../mach/mach/message.h ../../mach/mach/kern_return.h ../../mach/mach/mig_errors.h ../../mach/device/device_types.h.  */
+/* This file generated by errnos.awk.  */
 
 /* The Hurd uses Mach error system 0x10, currently only subsystem 0. */
 #ifndef _HURD_ERRNO
diff --git a/sysdeps/mach/hurd/fork.c b/sysdeps/mach/hurd/fork.c
index 5814cc2db2..234e377609 100644
--- a/sysdeps/mach/hurd/fork.c
+++ b/sysdeps/mach/hurd/fork.c
@@ -61,9 +61,7 @@ __fork (void)
   struct hurd_sigstate *volatile ss;
 
   ss = _hurd_self_sigstate ();
-  __spin_lock (&ss->lock);
-  ss->critical_section = 1;
-  __spin_unlock (&ss->lock);
+  __spin_lock (&ss->critical_section_lock);
 
 #undef	LOSE
 #define LOSE assert_perror (err) /* XXX */
@@ -606,7 +604,7 @@ __fork (void)
 					     &_hurd_orphaned));
 
       /* Forking clears the trace flag.  */
-      _hurd_exec_flags &= ~EXEC_TRACED;
+      __sigemptyset (&_hurdsig_traced);
 
       /* Run things that want to run in the child task to set up.  */
       RUN_HOOK (_hurd_fork_child_hook, ());
diff --git a/sysdeps/mach/hurd/i386/sigreturn.c b/sysdeps/mach/hurd/i386/sigreturn.c
index d47b863fe1..7adcadfb52 100644
--- a/sysdeps/mach/hurd/i386/sigreturn.c
+++ b/sysdeps/mach/hurd/i386/sigreturn.c
@@ -58,7 +58,7 @@ __sigreturn (struct sigcontext *scp)
 	 arrange to have us called over again in the new reality.  */
       ss->context = scp;
       __spin_unlock (&ss->lock);
-      __msg_sig_post (_hurd_msgport, 0, __mach_task_self ());
+      __msg_sig_post (_hurd_msgport, 0, 0, __mach_task_self ());
       /* If a pending signal was handled, sig_post never returned.
 	 If it did return, the pending signal didn't run a handler;
 	 proceed as usual.  */
diff --git a/sysdeps/mach/hurd/jmp-unwind.c b/sysdeps/mach/hurd/jmp-unwind.c
index 20ca5f8aa6..fcb09119ce 100644
--- a/sysdeps/mach/hurd/jmp-unwind.c
+++ b/sysdeps/mach/hurd/jmp-unwind.c
@@ -41,14 +41,15 @@ _longjmp_unwind (jmp_buf env, int val)
   /* All access to SS->active_resources must take place inside a critical
      section where signal handlers cannot run.  */
   __spin_lock (&ss->lock);
-  assert (! ss->critical_section);
-  ss->critical_section = 1;
+  assert (! __spin_lock_locked (&ss->critical_section_lock));
+  __spin_lock (&ss->critical_section_lock);
 
   /* Remove local signal preempters being unwound past.  */
   while (ss->preempters &&
 	 _JMPBUF_UNWINDS (env[0].__jmpbuf, ss->preempters))
     ss->preempters = ss->preempters->next;
 
+  __spin_unlock (&ss->critical_section_lock);
   __spin_unlock (&ss->lock);
 
   /* Iterate over the current thread's list of active resources.
diff --git a/sysdeps/mach/hurd/kill.c b/sysdeps/mach/hurd/kill.c
index 1f10613b09..6dcc5b530f 100644
--- a/sysdeps/mach/hurd/kill.c
+++ b/sysdeps/mach/hurd/kill.c
@@ -65,7 +65,7 @@ __kill (pid_t pid, int sig)
 	    {
 	      if (msgport != MACH_PORT_NULL)
 		/* Send a signal message to his message port.  */
-		return __msg_sig_post (msgport, sig, refport);
+		return __msg_sig_post (msgport, sig, 0, refport);
 
 	      /* The process has no message port.  Perhaps try direct
 		 frobnication of the task.  */
diff --git a/sysdeps/mach/hurd/ptrace.c b/sysdeps/mach/hurd/ptrace.c
index f68d3b41ed..24cf9469d5 100644
--- a/sysdeps/mach/hurd/ptrace.c
+++ b/sysdeps/mach/hurd/ptrace.c
@@ -1,5 +1,5 @@
 /* Process tracing interface `ptrace' for GNU Hurd.
-Copyright (C) 1991, 1992, 1993, 1995 Free Software Foundation, Inc.
+Copyright (C) 1991, 1992, 1993, 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
@@ -93,7 +93,7 @@ ptrace (enum __ptrace_request request, ... )
     {
     case PTRACE_TRACEME:
       /* Make this process be traced.  */
-      _hurd_exec_flags |= EXEC_TRACED;
+      __sigfillset (&_hurdsig_traced);
       __USEPORT (PROC, __proc_mark_traced (port));
       break;
 
@@ -144,7 +144,7 @@ ptrace (enum __ptrace_request request, ... )
 	      /* Tell the process to take the signal (or just resume if 0).  */
 	      err = HURD_MSGPORT_RPC
 		(__USEPORT (PROC, __proc_getmsgport (port, pid, &msgport)),
-		 0, 0, __msg_sig_post_untraced (msgport, data, task));
+		 0, 0, __msg_sig_post_untraced (msgport, data, 0, task));
 	  }
 	__mach_port_deallocate (__mach_task_self (), task);
 	return err ? __hurd_fail (err) : 0;
@@ -178,25 +178,17 @@ ptrace (enum __ptrace_request request, ... )
 	err = __USEPORT (PROC, __proc_getmsgport (port, pid, &msgport));
 	if (! err)
 	  {
-	    err = (request == PTRACE_ATTACH ?
-		   __msg_set_some_exec_flags :
-		   __msg_clear_some_exec_flags) (msgport, task, EXEC_TRACED);
-#ifdef notyet			/* XXX */
-	    if (! err)
-	      /* Request (or request an end to) SIGCHLD notification
-		 when PID stops or dies, and proc_wait working on PID.  */
-	      err = __USEPORT (PROC,
-			       __proc_trace_pid (port, pid,
-						 request == PTRACE_ATTACH));
-#endif
+	    err = __msg_set_init_int (msgport, task, INIT_TRACEMASK,
+				      request == PTRACE_DETACH ? 0 :
+				      ~(sigset_t) 0);
 	    if (! err)
 	      {
 		if (request == PTRACE_ATTACH)
 		  /* Now stop the process.  */
-		  err = __msg_sig_post (msgport, SIGSTOP, task);
+		  err = __msg_sig_post (msgport, SIGSTOP, 0, task);
 		else
 		  /* Resume the process from tracing stop.  */
-		  err = __msg_sig_post_untraced (msgport, 0, task);
+		  err = __msg_sig_post_untraced (msgport, 0, 0, task);
 	      }
 	    __mach_port_deallocate (__mach_task_self (), msgport);
 	  }
diff --git a/sysdeps/mach/hurd/select.c b/sysdeps/mach/hurd/select.c
index 8e78adb1bc..188f65b3c0 100644
--- a/sysdeps/mach/hurd/select.c
+++ b/sysdeps/mach/hurd/select.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991, 1992, 1993, 1994, 1995, 1996 Free Software Foundation, Inc.
+/* Copyright (C) 1991, 92, 93, 94, 95, 96 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
@@ -22,6 +22,7 @@ Cambridge, MA 02139, USA.  */
 #include <hurd/fd.h>
 #include <stdlib.h>
 #include <string.h>
+#include <assert.h>
 
 /* All user select types.  */
 #define SELECT_ALL (SELECT_READ | SELECT_WRITE | SELECT_URG)
@@ -41,12 +42,8 @@ DEFUN(__select, (nfds, readfds, writefds, exceptfds, timeout),
       fd_set *exceptfds AND struct timeval *timeout)
 {
   int i;
-  mach_port_t port;
+  mach_port_t portset;
   int got;
-  int *types;
-  struct hurd_userlink *ulink;
-  mach_port_t *ports;
-  struct hurd_fd **cells;
   error_t err;
   fd_set rfds, wfds, xfds;
   int firstfd, lastfd;
@@ -54,6 +51,14 @@ DEFUN(__select, (nfds, readfds, writefds, exceptfds, timeout),
 			   (timeout->tv_sec * 1000 +
 			    timeout->tv_usec / 1000) :
 			   0);
+  struct
+    {
+      struct hurd_userlink ulink;
+      struct hurd_fd *cell;
+      mach_port_t io_port;
+      int type;
+      mach_port_t reply_port;
+    } d[nfds];
 
   /* Use local copies so we can't crash from user bogosity.  */
   if (readfds == NULL)
@@ -76,10 +81,6 @@ DEFUN(__select, (nfds, readfds, writefds, exceptfds, timeout),
     nfds = _hurd_dtablesize;
 
   /* Collect the ports for interesting FDs.  */
-  cells = __alloca (nfds * sizeof (*cells));
-  ports = __alloca (nfds * sizeof (*ports));
-  types = __alloca (nfds * sizeof (*types));
-  ulink = __alloca (nfds * sizeof (*ulink));
   firstfd = lastfd = -1;
   for (i = 0; i < nfds; ++i)
     {
@@ -90,16 +91,16 @@ DEFUN(__select, (nfds, readfds, writefds, exceptfds, timeout),
 	type |= SELECT_WRITE;
       if (exceptfds != NULL && FD_ISSET (i, &xfds))
 	type |= SELECT_URG;
-      types[i] = type;
+      d[i].type = type;
       if (type)
 	{
-	  cells[i] = _hurd_dtable[i];
-	  ports[i] = _hurd_port_get (&cells[i]->port, &ulink[i]);
-	  if (ports[i] == MACH_PORT_NULL)
+	  d[i].cell = _hurd_dtable[i];
+	  d[i].io_port = _hurd_port_get (&d[i].cell->port, &d[i].ulink);
+	  if (d[i].io_port == MACH_PORT_NULL)
 	    {
 	      /* If one descriptor is bogus, we fail completely.  */
 	      while (i-- > 0)
-		_hurd_port_free (&cells[i]->port, &ulink[i], ports[i]);
+		_hurd_port_free (&d[i].cell->port, &d[i].ulink, d[i].io_port);
 	      errno = EBADF;
 	      break;
 	    }
@@ -115,58 +116,63 @@ DEFUN(__select, (nfds, readfds, writefds, exceptfds, timeout),
   if (i < nfds)
     return -1;
 
-  /* Get a port to receive the io_select_reply messages on.  */
-  port = __mach_reply_port ();
-
   /* Send them all io_select request messages.  */
-  got = 0;
   err = 0;
+  got = 0;
+  portset = MACH_PORT_NULL;
   for (i = firstfd; i <= lastfd; ++i)
-    if (types[i])
+    if (d[i].type)
       {
-	if (!err)
+	int type = d[i].type;
+	d[i].reply_port = __mach_reply_port ();
+	err = __io_select (d[i].io_port, d[i].reply_port,
+			   /* Poll for each but the last.  */
+			   (i == lastfd && got == 0) ? to : 0,
+			   &type);
+	switch (err)
 	  {
-	    int tag = i;
-	    int type = types[i];
-	    err = __io_select (ports[i], port,
-			       /* Poll for each but the last.  */
-			       (i == lastfd && got == 0) ? to : 0,
-			       &type, &tag);
-	    switch (err)
+	  case MACH_RCV_TIMED_OUT:
+	    /* No immediate response.  This is normal.  */
+	    err = 0;
+	    if (got == 0)
 	      {
-	      case MACH_RCV_TIMED_OUT:
-		/* No immediate response.  This is normal.  */
-		err = 0;
-		break;
-
-	      case 0:
-		/* We got an answer.  This is not necessarily the answer to
-                   the query we sent just now.  It may correspond to any
-                   prior query which timed out before its answer arrived.  */
-		if (tag < 0 || tag > i || (type & SELECT_ALL) == 0)
-		  /* This is not a proper answer to any query we have yet
-                     made.  */
-		  err = EGRATUITOUS;
-		else
-		  {
-		    /* Some port is ready.  TAG tells us which.  */
-		    types[tag] &= type;
-		    types[tag] |= SELECT_RETURNED;
-		    ++got;
-		  }
-		break;
-
-	      default:
-		/* Any other error kills us.
-		   But we must continue to loop to free the ports.  */
-		break;
+		/* We will wait again for a reply later.  */
+		if (portset == MACH_PORT_NULL)
+		  /* Create the portset to receive all the replies on.  */
+		  err = __mach_port_allocate (__mach_task_self (),
+					      MACH_PORT_RIGHT_PORT_SET,
+					      &portset);
+		if (! err)
+		  /* Put this reply port in the port set.  */
+		  __mach_port_move_member (__mach_task_self (),
+					   d[i].reply_port, portset);
 	      }
+	    break;
+
+	  default:
+	    /* No other error should happen.  Callers of select don't
+	       expect to see errors, so we simulate readiness of the erring
+	       object and the next call hopefully will get the error again.  */
+	    type = SELECT_ALL;
+	    /* FALLTHROUGH */
+
+	  case 0:
+	    /* We got an answer.  */
+	    if ((type & SELECT_ALL) == 0)
+	      /* Bogus answer; treat like an error, as a fake positive.  */
+	      type = SELECT_ALL;
+
+	    /* This port is already ready already.  */
+	    d[i].type &= type;
+	    d[i].type |= SELECT_RETURNED;
+	    ++got;
+	    break;
 	  }
-	_hurd_port_free (&cells[i]->port, &ulink[i], ports[i]);
+	_hurd_port_free (&d[i].cell->port, &d[i].ulink, d[i].io_port);
       }
 
   /* Now wait for reply messages.  */
-  if (!err && got == 0 && port != MACH_PORT_NULL)
+  if (!err && got == 0)
     {
       /* Now wait for io_select_reply messages on PORT,
 	 timing out as appropriate.  */
@@ -187,15 +193,13 @@ DEFUN(__select, (nfds, readfds, writefds, exceptfds, timeout),
 	      error_t err;
 	      mach_msg_type_t result_type;
 	      int result;
-	      mach_msg_type_t tag_type;
-	      int tag;
 	    } success;
 	} msg;
       mach_msg_option_t options = (timeout == NULL ? 0 : MACH_RCV_TIMEOUT);
       error_t msgerr;
       while ((msgerr = __mach_msg (&msg.head,
 				   MACH_RCV_MSG | options,
-				   0, sizeof msg, port, to,
+				   0, sizeof msg, portset, to,
 				   MACH_PORT_NULL)) == MACH_MSG_SUCCESS)
 	{
 	  /* We got a message.  Decode it.  */
@@ -209,34 +213,45 @@ DEFUN(__select, (nfds, readfds, writefds, exceptfds, timeout),
 	    {
 	      /* This is a properly formatted message so far.
 		 See if it is a success or a failure.  */
-	      if (msg.error.err)
+	      if (msg.error.err == EINTR &&
+		  msg.head.msgh_size == sizeof msg.error)
 		{
-		  err = msg.error.err;
-		  if (msg.head.msgh_size != sizeof msg.error)
-		    __mach_msg_destroy (&msg);
+		  /* EINTR response; poll for further responses
+		     and then return quickly.  */
+		  err = EINTR;
+		  goto poll;
 		}
-	      else if (msg.head.msgh_size != sizeof msg.success ||
-		       *(int *) &msg.success.tag_type != *(int *) &inttype ||
-		       *(int *) &msg.success.result_type != *(int *) &inttype)
-		__mach_msg_destroy (&msg);
-	      else if ((msg.success.result & SELECT_ALL) == 0 ||
-		       msg.success.tag < firstfd || msg.success.tag > lastfd)
-		err = EGRATUITOUS;
-	      else
+	      if (msg.error.err ||
+		  msg.head.msgh_size != sizeof msg.success ||
+		  *(int *) &msg.success.result_type != *(int *) &inttype ||
+		  (msg.success.result & SELECT_ALL) == 0)
 		{
-		  /* This is a winning io_select_reply message!
-		     Record the readiness it indicates and send a reply.  */
-		  types[msg.success.tag] &= msg.success.result;
-		  types[msg.success.tag] |= SELECT_RETURNED;
-		  ++got;
+		  /* Error or bogus reply.  Simulate readiness.  */
+		  __mach_msg_destroy (&msg);
+		  msg.success.result = SELECT_ALL;
 		}
+
+	      /* Look up the respondant's reply port and record its
+                 readiness.  */
+	      {
+		int had = got;
+		for (i = firstfd; i <= lastfd; ++i)
+		  if (d[i].type && d[i].reply_port == msg.head.msgh_local_port)
+		    {
+		      d[i].type &= msg.success.result;
+		      d[i].type |= SELECT_RETURNED;
+		      ++got;
+		    }
+		assert (got > had);
+	      }
 	    }
 
 	  if (msg.head.msgh_remote_port != MACH_PORT_NULL)
 	    __mach_port_deallocate (__mach_task_self (),
 				    msg.head.msgh_remote_port);
 
-	  if (got || err == EINTR)
+	  if (got)
+	  poll:
 	    {
 	      /* Poll for another message.  */
 	      to = 0;
@@ -252,19 +267,17 @@ DEFUN(__select, (nfds, readfds, writefds, exceptfds, timeout),
 	   message waiting.  */
 	err = 0;
 
-      if (got && err == EINTR)
-	/* Some calls were interrupted, but at least one descriptor
-	   is known to be ready now, so we will return success.  */
+      if (got)
+	/* At least one descriptor is known to be ready now, so we will
+	   return success.  */
 	err = 0;
     }
 
-  if (port != MACH_PORT_NULL)
-    /* We must destroy the port if we made some select requests
-       that might send notification on that port after we no longer care.
-       If the port were reused, that notification could confuse the next
-       select call to use the port.  The notification might be valid,
-       but the descriptor may have changed to a different server.  */
-    __mach_port_destroy (__mach_task_self (), port);
+  for (i = firstfd; i <= lastfd; ++i)
+    if (d[i].type)
+      __mach_port_destroy (__mach_task_self (), d[i].reply_port);
+  if (portset != MACH_PORT_NULL)
+    __mach_port_destroy (__mach_task_self (), portset);
 
   if (err)
     return __hurd_fail (err);
@@ -277,7 +290,7 @@ DEFUN(__select, (nfds, readfds, writefds, exceptfds, timeout),
      ones are initially set.  */
   for (i = firstfd; i <= lastfd; ++i)
     {
-      int type = types[i];
+      int type = d[i].type;
 
       if ((type & SELECT_RETURNED) == 0)
 	type = 0;
diff --git a/sysdeps/mach/hurd/sigaction.c b/sysdeps/mach/hurd/sigaction.c
index 957068b168..ebe70664be 100644
--- a/sysdeps/mach/hurd/sigaction.c
+++ b/sysdeps/mach/hurd/sigaction.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
+/* Copyright (C) 1991, 92, 93, 94, 95, 96 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
@@ -47,6 +47,7 @@ DEFUN(__sigaction, (sig, act, oact),
 
   ss = _hurd_self_sigstate ();
 
+  __spin_lock (&ss->critical_section_lock);
   __spin_lock (&ss->lock);
   old = ss->actions[sig];
   if (act != NULL)
@@ -55,7 +56,6 @@ DEFUN(__sigaction, (sig, act, oact),
   if (act != NULL && sig == SIGCHLD &&
       (a.sa_flags & SA_NOCLDSTOP) != (old.sa_flags & SA_NOCLDSTOP))
     {
-      ss->critical_section = 1;
       __spin_unlock (&ss->lock);
 
       /* Inform the proc server whether or not it should send us SIGCHLD for
@@ -65,16 +65,16 @@ DEFUN(__sigaction, (sig, act, oact),
 		 __proc_mod_stopchild (port, !(a.sa_flags & SA_NOCLDSTOP)));
 
       __spin_lock (&ss->lock);
-      ss->critical_section = 0;
       pending = ss->pending & ~ss->blocked;
     }
   else
     pending = 0;
 
   __spin_unlock (&ss->lock);
+  __spin_unlock (&ss->critical_section_lock);
 
   if (pending)
-    __msg_sig_post (_hurd_msgport, 0, __mach_task_self ());
+    __msg_sig_post (_hurd_msgport, 0, 0, __mach_task_self ());
 
   if (oact != NULL)
     *oact = old;
diff --git a/sysdeps/mach/hurd/sigprocmask.c b/sysdeps/mach/hurd/sigprocmask.c
index bae3266708..36edd2bfd5 100644
--- a/sysdeps/mach/hurd/sigprocmask.c
+++ b/sysdeps/mach/hurd/sigprocmask.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
+/* Copyright (C) 1991, 1992, 1993, 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
@@ -79,7 +79,7 @@ DEFUN(__sigprocmask, (how, set, oset),
   if (pending)
     /* Send a message to the signal thread so it
        will wake up and check for pending signals.  */
-    __msg_sig_post (_hurd_msgport, 0, __mach_task_self ());
+    __msg_sig_post (_hurd_msgport, 0, 0, __mach_task_self ());
 
   return 0;
 }
diff --git a/sysdeps/mach/hurd/sigsuspend.c b/sysdeps/mach/hurd/sigsuspend.c
index aa0b2876a4..d8ac97032d 100644
--- a/sysdeps/mach/hurd/sigsuspend.c
+++ b/sysdeps/mach/hurd/sigsuspend.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
+/* Copyright (C) 1991, 1992, 1993, 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
@@ -57,7 +57,7 @@ DEFUN(sigsuspend, (set), CONST sigset_t *set)
 
   if (pending)
     /* Tell the signal thread to check for pending signals.  */
-    __msg_sig_post (_hurd_msgport, 0, __mach_task_self ());
+    __msg_sig_post (_hurd_msgport, 0, 0, __mach_task_self ());
 
   /* Wait for the signal thread's message.  */
   __mach_msg (&msg, MACH_RCV_MSG, 0, sizeof (msg), wait,
@@ -71,8 +71,8 @@ DEFUN(sigsuspend, (set), CONST sigset_t *set)
 
   if (pending)
     /* Tell the signal thread to check for pending signals.  */
-    __msg_sig_post (_hurd_msgport, 0, __mach_task_self ());
-    
+    __msg_sig_post (_hurd_msgport, 0, 0, __mach_task_self ());
+
   /* We've been interrupted!  And a good thing, too.
      Otherwise we'd never return.
      That's right; this function always returns an error.  */