summary refs log tree commit diff
path: root/hurd/dtable.c
diff options
context:
space:
mode:
Diffstat (limited to 'hurd/dtable.c')
-rw-r--r--hurd/dtable.c103
1 files changed, 67 insertions, 36 deletions
diff --git a/hurd/dtable.c b/hurd/dtable.c
index 30f6a5ee82..f3eb88fb3a 100644
--- a/hurd/dtable.c
+++ b/hurd/dtable.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991, 92, 93, 94, 95, 96, 97 Free Software Foundation, Inc.
+/* Copyright (C) 1991,92,93,94,95,96,97,99 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
@@ -107,18 +107,35 @@ text_set_element (_hurd_subinit, init_dtable);
 static file_t
 get_dtable_port (int fd)
 {
+  struct hurd_fd *d = _hurd_fd_get (fd);
   file_t dport;
-  int err = HURD_DPORT_USE (fd, __mach_port_mod_refs (__mach_task_self (),
-						      (dport = port),
-						      MACH_PORT_RIGHT_SEND,
-						      1));
-  if (err)
-    {
-      errno = err;
-      return MACH_PORT_NULL;
-    }
-  else
-    return dport;
+
+  if (!d)
+    return __hurd_fail (EBADF), MACH_PORT_NULL;
+
+  HURD_CRITICAL_BEGIN;
+
+  dport = HURD_PORT_USE (&d->port,
+			 ({
+			   error_t err;
+			   mach_port_t outport;
+			   err = __mach_port_mod_refs (__mach_task_self (),
+						       port,
+						       MACH_PORT_RIGHT_SEND,
+						       1);
+			   if (err)
+			     {
+			       errno = err;
+			       outport = MACH_PORT_NULL;
+			     }
+			   else
+			     outport = port;
+			   outport;
+			 }));
+
+  HURD_CRITICAL_END;
+
+  return dport;
 }
 
 file_t (*_hurd_getdport_fn) (int fd) = get_dtable_port;
@@ -176,32 +193,46 @@ ctty_new_pgrp (void)
   HURD_CRITICAL_BEGIN;
   __mutex_lock (&_hurd_dtable_lock);
 
-  for (i = 0; i < _hurd_dtablesize; ++i)
+  if (__USEPORT (CTTYID, port == MACH_PORT_NULL))
     {
-      struct hurd_fd *const d = _hurd_dtable[i];
-      struct hurd_userlink ulink, ctty_ulink;
-      io_t port, ctty;
-
-      if (d == NULL)
-	/* Nothing to do for an unused descriptor cell.  */
-	continue;
-
-      port = _hurd_port_get (&d->port, &ulink);
-      ctty = _hurd_port_get (&d->ctty, &ctty_ulink);
-
-      if (ctty != MACH_PORT_NULL)
-	{
-	  /* This fd has a ctty-special port.  We need a new one, to tell
-             the io server of our different process group.  */
-	  io_t new;
-	  if (__term_open_ctty (port, _hurd_pid, _hurd_pgrp, &new))
-	    new = MACH_PORT_NULL;
-	  _hurd_port_set (&d->ctty, new);
-	}
-
-      _hurd_port_free (&d->port, &ulink, port);
-      _hurd_port_free (&d->ctty, &ctty_ulink, ctty);
+      /* We have no controlling terminal.  If we haven't had one recently,
+	 but our pgrp is being pointlessly diddled anyway, then we will
+	 have nothing to do in the loop below because no fd will have a
+	 ctty port at all.
+
+	 More likely, a setsid call is responsible both for the change
+	 in pgrp and for clearing the cttyid port.  In that case, setsid
+	 held the dtable lock while updating the dtable to clear all the
+	 ctty ports, and ergo must have finished doing so before we run here.
+	 So we can be sure, again, that the loop below has no work to do.  */
     }
+  else
+    for (i = 0; i < _hurd_dtablesize; ++i)
+      {
+	struct hurd_fd *const d = _hurd_dtable[i];
+	struct hurd_userlink ulink, ctty_ulink;
+	io_t port, ctty;
+
+	if (d == NULL)
+	  /* Nothing to do for an unused descriptor cell.  */
+	  continue;
+
+	port = _hurd_port_get (&d->port, &ulink);
+	ctty = _hurd_port_get (&d->ctty, &ctty_ulink);
+
+	if (ctty != MACH_PORT_NULL)
+	  {
+	    /* This fd has a ctty-special port.  We need a new one, to tell
+	       the io server of our different process group.  */
+	    io_t new;
+	    if (__term_open_ctty (port, _hurd_pid, _hurd_pgrp, &new))
+	      new = MACH_PORT_NULL;
+	    _hurd_port_set (&d->ctty, new);
+	  }
+
+	_hurd_port_free (&d->port, &ulink, port);
+	_hurd_port_free (&d->ctty, &ctty_ulink, ctty);
+      }
 
   __mutex_unlock (&_hurd_dtable_lock);
   HURD_CRITICAL_END;