diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog
index b14ef4e8f..d824d8233 100644
--- a/winsup/cygwin/ChangeLog
+++ b/winsup/cygwin/ChangeLog
@@ -1,3 +1,25 @@
+Mon Sep 24 17:41:03 2001  Christopher Faylor <cgf@redhat.com>
+
+	* fhandler.h (fhandler_pipe::hit_eof): New method.
+	(writepipe_exists): New class element.
+	(orig_pid): Ditto.
+	(id): Ditto.
+	(is_slow): Eliminate.
+	* pipe.cc (fhandler_pipe::set_close_on_exec): Set inheritance on
+	writepipe_exists, if it exists.
+	(fhandler_pipe::hit_eof): New method, modelled after tty.
+	(fhandler_pipe::dup): Duplicate writepipe_exists, if it exists.
+	(make_pipe): Set up a dummy event for pipes on windows 9x.  The
+	nonexistence of this event means that the write side of the
+	pipe has closed.
+	(_dup): Move to syscalls.cc
+	(_dup2): Ditto.
+
+	* dtable.cc (dtable::build_fhandler): Fill out set_names here, if
+	appropriate.
+	* syscalls.cc (_open): Call set_names in build_fhandler.
+	
+	
 Sun Sep 23 16:55:00 2001  Corinna Vinschen <corinna@vinschen.de>
 
 	* syscalls.cc (_open): Set name in fhandler object after successful
diff --git a/winsup/cygwin/dtable.cc b/winsup/cygwin/dtable.cc
index d39713365..e08ed4209 100644
--- a/winsup/cygwin/dtable.cc
+++ b/winsup/cygwin/dtable.cc
@@ -232,6 +232,7 @@ dtable::build_fhandler (int fd, const char *name, HANDLE handle, path_conv *pc)
 {
   int unit;
   DWORD devn;
+  fhandler_base *fh;
 
   if (!pc)
     devn = get_device_number (name, unit);
@@ -265,7 +266,10 @@ dtable::build_fhandler (int fd, const char *name, HANDLE handle, path_conv *pc)
 	devn = FH_DISK;
     }
 
-  return build_fhandler (fd, devn, name, unit);
+  fh = build_fhandler (fd, devn, name, unit);
+  if (pc)
+    fh->set_name (name, *pc);
+  return fh;
 }
 
 fhandler_base *
diff --git a/winsup/cygwin/fhandler.h b/winsup/cygwin/fhandler.h
index 1fe6990d0..ed9ca350b 100644
--- a/winsup/cygwin/fhandler.h
+++ b/winsup/cygwin/fhandler.h
@@ -368,7 +368,7 @@ public:
   virtual HANDLE& get_handle () { return io_handle; }
   virtual HANDLE& get_io_handle () { return io_handle; }
   virtual HANDLE& get_output_handle () { return io_handle; }
-  virtual BOOL hit_eof () {return FALSE;}
+  virtual bool hit_eof () {return FALSE;}
   virtual select_record *select_read (select_record *s);
   virtual select_record *select_write (select_record *s);
   virtual select_record *select_except (select_record *s);
@@ -437,10 +437,12 @@ public:
 class fhandler_pipe: public fhandler_base
 {
   HANDLE guard;
+  HANDLE writepipe_exists;
+  DWORD orig_pid;
+  unsigned id;
 public:
   fhandler_pipe (const char *name = 0, DWORD devtype = FH_PIPE);
   off_t lseek (off_t offset, int whence);
-  BOOL is_slow () {return !wincap.has_unreliable_pipes ();}
   select_record *select_read (select_record *s);
   select_record *select_write (select_record *s);
   select_record *select_except (select_record *s);
@@ -450,6 +452,8 @@ public:
   int close ();
   void create_guard (SECURITY_ATTRIBUTES *sa) {guard = CreateMutex (sa, FALSE, NULL);}
   int dup (fhandler_base *child);
+  bool hit_eof ();
+  friend int make_pipe (int fildes[2], unsigned int psize, int mode);
 };
 
 class fhandler_dev_raw: public fhandler_base
@@ -863,7 +867,7 @@ public:
   char *ptsname ();
 
   void set_close_on_exec (int val);
-  BOOL hit_eof ();
+  bool hit_eof ();
 };
 
 class fhandler_tty_master: public fhandler_pty_master
diff --git a/winsup/cygwin/fhandler_tty.cc b/winsup/cygwin/fhandler_tty.cc
index 4aa3b0572..1a46ecb3b 100644
--- a/winsup/cygwin/fhandler_tty.cc
+++ b/winsup/cygwin/fhandler_tty.cc
@@ -223,7 +223,7 @@ process_input (void *)
     }
 }
 
-BOOL
+bool
 fhandler_pty_master::hit_eof ()
 {
   if (get_ttyp ()->was_opened && !get_ttyp ()->slave_alive ())
diff --git a/winsup/cygwin/how-vfork-works.txt b/winsup/cygwin/how-vfork-works.txt
index c45228cad..7148366db 100644
--- a/winsup/cygwin/how-vfork-works.txt
+++ b/winsup/cygwin/how-vfork-works.txt
@@ -28,8 +28,8 @@ the result of a vfork and closes the extra file handles.
 
 This all relies on the fact that the child in a vfork call can affect
 just about everything in the parent except for the parent's fds.
-The assumption is that you don't return from the call that invoked the
-vfork.
+The assumption is that a vfork is always just used as a method for
+starting a program.
 
 The assumption is also that all of this is much faster than the
 slow method that cygwin uses to implement fork().
diff --git a/winsup/cygwin/pipe.cc b/winsup/cygwin/pipe.cc
index 04a1fbece..aab242b89 100644
--- a/winsup/cygwin/pipe.cc
+++ b/winsup/cygwin/pipe.cc
@@ -18,9 +18,15 @@ details. */
 #include "dtable.h"
 #include "cygheap.h"
 #include "thread.h"
+#include "sigproc.h"
+#include "pinfo.h"
+
+static unsigned pipecount;
+static const NO_COPY char pipeid_fmt[] = "stupid_pipe.%u.%u";
 
 fhandler_pipe::fhandler_pipe (const char *name, DWORD devtype) :
-	fhandler_base (devtype, name), guard (0)
+	fhandler_base (devtype, name),
+	guard (0), writepipe_exists(0), orig_pid (0), id (0)
 {
   set_cb (sizeof *this);
 }
@@ -37,7 +43,10 @@ void
 fhandler_pipe::set_close_on_exec (int val)
 {
   this->fhandler_base::set_close_on_exec (val);
-  set_inheritance (guard, val);
+  if (guard)
+    set_inheritance (guard, val);
+  if (writepipe_exists)
+    set_inheritance (writepipe_exists, val);
 }
 
 int
@@ -53,9 +62,27 @@ int fhandler_pipe::close ()
   int res = this->fhandler_base::close ();
   if (guard)
     CloseHandle (guard);
+  if (writepipe_exists)
+{debug_printf ("writepipe_exists closed");
+    CloseHandle (writepipe_exists);
+}
   return res;
 }
 
+bool
+fhandler_pipe::hit_eof ()
+{
+  char buf[80];
+  HANDLE ev;
+  if (!orig_pid)
+    return bg_ok;
+  __small_sprintf (buf, pipeid_fmt, orig_pid, id);
+  if ((ev = OpenEvent (EVENT_ALL_ACCESS, FALSE, buf)))
+    CloseHandle (ev);
+  debug_printf ("%s %p", buf, ev);
+  return ev == NULL;
+}
+
 int
 fhandler_pipe::dup (fhandler_base *child)
 {
@@ -70,10 +97,21 @@ fhandler_pipe::dup (fhandler_base *child)
   else if (!DuplicateHandle (hMainProc, guard, hMainProc, &ftp->guard, 0, 1,
 			     DUPLICATE_SAME_ACCESS))
     return -1;
+
+  if (writepipe_exists == NULL)
+    ftp->writepipe_exists = NULL;
+  else if (!DuplicateHandle (hMainProc, writepipe_exists, hMainProc,
+			     &ftp->writepipe_exists, 0, 1,
+			     DUPLICATE_SAME_ACCESS))
+    return -1;
+
+  ftp->id = id;
+  ftp->orig_pid = orig_pid;
   return 0;
 }
 
-static int
+
+int
 make_pipe (int fildes[2], unsigned int psize, int mode)
 {
   SetResourceLock (LOCK_FD_LIST, WRITE_LOCK | READ_LOCK, "make_pipe");
@@ -108,6 +146,15 @@ make_pipe (int fildes[2], unsigned int psize, int mode)
 
       res = 0;
       fhr->create_guard (sa);
+      if (wincap.has_unreliable_pipes ())
+	{
+	  char buf[80];
+	  int count = pipecount++;	/* FIXME: Should this be InterlockedIncrement? */
+	  __small_sprintf (buf, pipeid_fmt, myself->pid, count);
+	  fhw->writepipe_exists = CreateEvent (sa, TRUE, FALSE, buf);
+	  fhr->orig_pid = myself->pid;
+	  fhr->id = count;
+	}
     }
 
   syscall_printf ("%d = make_pipe ([%d, %d], %d, %p)", res, fdr, fdw, psize, mode);
@@ -131,22 +178,3 @@ _pipe (int filedes[2], unsigned int psize, int mode)
     cygheap->fdtab[filedes[0]]->set_r_no_interrupt (1);
   return res;
 }
-
-int
-dup (int fd)
-{
-  int res;
-  SetResourceLock (LOCK_FD_LIST, WRITE_LOCK | READ_LOCK, "dup");
-
-  res = dup2 (fd, cygheap->fdtab.find_unused_handle ());
-
-  ReleaseResourceLock(LOCK_FD_LIST, WRITE_LOCK | READ_LOCK, "dup");
-
-  return res;
-}
-
-int
-dup2 (int oldfd, int newfd)
-{
-  return cygheap->fdtab.dup2 (oldfd, newfd);
-}
diff --git a/winsup/cygwin/select.cc b/winsup/cygwin/select.cc
index 67365d925..b01d833ef 100644
--- a/winsup/cygwin/select.cc
+++ b/winsup/cygwin/select.cc
@@ -420,11 +420,6 @@ peek_pipe (select_record *s, int ignra, HANDLE guard_mutex = NULL)
 	  gotone = 1;
 	  goto out;
 	}
-      if (fh->bg_check (SIGTTIN) <= bg_eof)
-	{
-	  gotone = s->read_ready = 1;
-	  goto out;
-	}
 
       switch (fh->get_device ())
 	{
@@ -444,6 +439,12 @@ peek_pipe (select_record *s, int ignra, HANDLE guard_mutex = NULL)
 	      goto out;
 	    }
 	}
+
+      if (fh->bg_check (SIGTTIN) <= bg_eof)
+	{
+	  gotone = s->read_ready = 1;
+	  goto out;
+	}
     }
 
   if (fh->get_device () == FH_PIPEW)
diff --git a/winsup/cygwin/syscalls.cc b/winsup/cygwin/syscalls.cc
index 559582bfd..9f5c8ac88 100644
--- a/winsup/cygwin/syscalls.cc
+++ b/winsup/cygwin/syscalls.cc
@@ -81,6 +81,25 @@ check_ttys_fds (void)
   return res;
 }
 
+int
+dup (int fd)
+{
+  int res;
+  SetResourceLock (LOCK_FD_LIST, WRITE_LOCK | READ_LOCK, "dup");
+
+  res = dup2 (fd, cygheap->fdtab.find_unused_handle ());
+
+  ReleaseResourceLock(LOCK_FD_LIST, WRITE_LOCK | READ_LOCK, "dup");
+
+  return res;
+}
+
+int
+dup2 (int oldfd, int newfd)
+{
+  return cygheap->fdtab.dup2 (oldfd, newfd);
+}
+
 extern "C" int
 _unlink (const char *ourname)
 {
@@ -489,17 +508,13 @@ _open (const char *unix_path, int flags, ...)
 	  path_conv pc;
 	  if (!(fh = cygheap->fdtab.build_fhandler (fd, unix_path, NULL, &pc)))
 	    res = -1;		// errno already set
-	  else 
+	  else if (!fh->open (pc, flags, (mode & 07777) & ~cygheap->umask))
 	    {
-	      fh->set_name (unix_path, pc.get_win32 ());
-	      if (!fh->open (pc, flags, (mode & 07777) & ~cygheap->umask))
-		{
-		  cygheap->fdtab.release (fd);
-		  res = -1;
-		}
-	      else if ((res = fd) <= 2)
-		set_std_handle (res);
+	      cygheap->fdtab.release (fd);
+	      res = -1;
 	    }
+	  else if ((res = fd) <= 2)
+	    set_std_handle (res);
 	}
       ReleaseResourceLock (LOCK_FD_LIST,WRITE_LOCK|READ_LOCK," open");
     }