OSDN Git Service

* child_info.h (child_info_spawn::hexec_proc): Eliminate.
authorcgf <cgf>
Fri, 26 Nov 2004 04:15:05 +0000 (04:15 +0000)
committercgf <cgf>
Fri, 26 Nov 2004 04:15:05 +0000 (04:15 +0000)
* dcrt0.cc (dll_crt0_0): Remove hexec_proc stuff.
* fork.cc (fork_child): Remove call to pinfo_fixup_after_fork.
* pinfo.cc (set_myself): Close and zero pid_handle if set.
(pinfo_fixup_after_fork): Delete.
(proc_waiter): Don't close vchild.hProcess here.  Do that when we are remove
the vchild from procs.  Save hProcess as pid_handle only on first reparent
operation.
(pinfo::wait): Don't set pid_handle here.
(pinfo::alert_parent): Always try to send signal.  If unsuccessful then close
and zero wr_proc_pipe.
* pinfo.h (pinfo::pinfo): Make sure that appropriate parts of the class are
zeroed on construction.
(pinfo::alert_parent): Take char argument.
(pinfo_fixup_after_fork): Delete declaration.
(hexec_proc): Ditto.
* sigproc.cc (remove_proc): Close pid_handle and hProcess if appropriate.
* spawn.cc (spawn_guts): Set cygheap->pid_handle on first exec.
* cygheap.h (init_cygheap::pid_handle): New element.
* pinfo.cc (set_myself): Clear previously existing cygheap->pid_handle when a
new process has been started.
(pinfo::wait): Make sure that a handle to the newly forked/spawned process is
kept around so that the pid will not be reused.
* pinfo.h (_pinfo::pid_handle): Move.
(pinfo::pid_handle): to here.
* spawn.cc (spawn_guts): Create a pid_handle in cygheap prior to spawning to
ensure that the pid does not get reused during the lifetime of the "cygwin
pid".
* pinfo.h (pinfo::alert_parent): New function.
* exceptions.cc (sig_handle_tty_stop): Use alert_parent to send "signals" to
parent.
* fork.cc (fork_parent): Don't close pi.hProcess.  Let the waiter thread do
that.
* pinfo.cc (proc_waiter): Detect case where process exits without setting the
exit code and use value from GetExitCodeProcess.  Reluctantly implement
__SIGREPARENT.
(pinfo::alert_parent): Define.
* sigproc.h (__SIGREPARENT): New enum.
* spawn.cc (spawn_guts): Send reparent signal to parent on exec.  Always create
process in suspended state to avoid races.  Remove cygthread.h in favor of
cygtls.h throughout since cygtls now includes cygthread.h.  Eliminate
ppid_handle usage throughout.
* child_info.h: Regenerate magic number
(child_info): Remove pppid_handle.
* cygthread.h (cygthread::release): New method.  Frees thread without waiting.
* cygthread.cc (cygthread::stub): Set _ctinfo in _mytls to point to information
for executing thread.  Don't call SetEvent if thread is no longer in use.
(cygthread::simplestub): Ditto.
* cygtls.h (_cygtls::_ctinfo): New element contains pointer to information
about executing cygthread, if any.
* dcrt0.cc: Remove last vestiges of per_thread stuff.
(dll_crt0_0): Ditto.  Remove accommodation for ppid_handle.
(do_exit): Remove obsolete reparenting test.
(_exit): Exit with a more SUSv3-like exit value.
* dtable.cc (dtable::stdio_init): Check for myself->cygstarted rather than
myself->ppid_handle to see if we were started by a cygwin process.
* exceptions.cc (open_stackdumpfile): Ditto.
(handle_exceptions): Ditto.
(ctrl_c_handler): Ditto.
(sig_handle_tty_stop): Ditto.  Let parent send signal to itself on STOP.
(sigpacket::process): Comment out vfork test.
(signal_exit): Use more SUSv3-like exit value on signal.
* external.cc (fillout_pinfo): Don't set hProcess.
* fork.cc: Remove VFORK cruft.
(per_thread::set): Delete.
(fork_child): Remove perthread stuff.
(fork_parent): Remove obsolete subproc_init.  Accommodate new method for
tracking subprocesses.
* pinfo.cc (set_myself): Accommodate new pinfo/_pinfo layout.  Set some things
here that used to be set in wait_sig.
(_pinfo::exit): Set exitcode here.  Close process pipe.
(_pinfo::commune_send): Accommodeate new pinfo/_pinfo layout.
(proc_waiter): New function.  Waits, in a thread for subprocess to go away.
(pinfo::wait): New function.  Initialization for proc_waiter.
* pinfo.h (_pinfo::exitcode): New element.
(_pinfo::cygstarted): Ditto.
(_pinfo::wr_proc_pipe): Ditto.
(_pinfo::ppid_handle): Delete.
(_pinfo::hProcess): Delete.
(_pinfo::lock): Delete.
(pinfo::hProcess): New element.
(pinfo::lock): Ditto.
(pinfo::wait): Declare new function.
(pinfo::preserve): Define new function.
* sigproc.cc: Remove old stuff from wait_subproc thread based method.
(zombies): Remove.
(procs): New.
(my_parent_is_alive): Just check that the parent pid exists.
(mychild): Just use pinfo methods to determine if child is mine.
(proc_subproc): Revamp PROC_ADDCHILD to use pinfo::wait.  Remove
PROC_CHILDTERMINATED logic.  Use different method to remove processes from list
when SIGCHLD == SIG_IGN.
(proc_terminate): Gut.
(subproc_init): Delete.
(init_child_info): Remove setting of pppid_handle.
(checkstate): Revamp to only scan procs array.
(remove_proc): Rename from remove_zombie.  Don't close hProcess or pid_handle.
Don't release memory if it's myself.
(stopped_or_terminated): Change logic to handle new consolidated proc/zombie
array.
(wait_subproc): Delete.
* sigproc.h: Remove obsolete EXIT_* defines.
(subproc_init): Remove declaration.
* spawn.cc (spawn_guts): Remove reparenting stuff.  Use standard wait logic to
wait for child if started from a non-cygwin process.
* tlsoffsets.h: Regenerate.
* tty.cc (tty_init): Check for myself->cygstarted rather than
myself->ppid_handle to see if we were started by a cygwin process.
* include/sys/signal.h (external_pinfo::exitcode): Replace hProcess.
* include/sys/wait.h (WCOREDUMP): Define.
* fhandler_tty.cc (fhandler_tty_slave::read): Add debugging output for timeout
case.
* signal.cc (abort): Flag that we are exiting with the ABORT signal.

33 files changed:
winsup/cygwin/ChangeLog
winsup/cygwin/child_info.h
winsup/cygwin/cygheap.h
winsup/cygwin/cygthread.cc
winsup/cygwin/cygthread.h
winsup/cygwin/cygtls.cc
winsup/cygwin/cygtls.h
winsup/cygwin/dcrt0.cc
winsup/cygwin/debug.cc
winsup/cygwin/dtable.cc
winsup/cygwin/exceptions.cc
winsup/cygwin/external.cc
winsup/cygwin/fhandler_console.cc
winsup/cygwin/fhandler_tty.cc
winsup/cygwin/fork.cc
winsup/cygwin/include/sys/cygwin.h
winsup/cygwin/include/sys/wait.h
winsup/cygwin/init.cc
winsup/cygwin/perthread.h [deleted file]
winsup/cygwin/pinfo.cc
winsup/cygwin/pinfo.h
winsup/cygwin/select.cc
winsup/cygwin/signal.cc
winsup/cygwin/sigproc.cc
winsup/cygwin/sigproc.h
winsup/cygwin/spawn.cc
winsup/cygwin/syscalls.cc
winsup/cygwin/timer.cc
winsup/cygwin/times.cc
winsup/cygwin/tlsoffsets.h
winsup/cygwin/tty.cc
winsup/cygwin/wait.cc
winsup/cygwin/window.cc

index 8d999c2..600ca06 100644 (file)
@@ -1,3 +1,134 @@
+2004-11-25  Christopher Faylor  <cgf@timesys.com>
+
+       * child_info.h (child_info_spawn::hexec_proc): Eliminate.
+       * dcrt0.cc (dll_crt0_0): Remove hexec_proc stuff.
+       * fork.cc (fork_child): Remove call to pinfo_fixup_after_fork.
+       * pinfo.cc (set_myself): Close and zero pid_handle if set.
+       (pinfo_fixup_after_fork): Delete.
+       (proc_waiter): Don't close vchild.hProcess here.  Do that when we are
+       remove the vchild from procs.  Save hProcess as pid_handle only on
+       first reparent operation.
+       (pinfo::wait): Don't set pid_handle here.
+       (pinfo::alert_parent): Always try to send signal.  If unsuccessful then
+       close and zero wr_proc_pipe.
+       * pinfo.h (pinfo::pinfo): Make sure that appropriate parts of the class
+       are zeroed on construction.
+       (pinfo::alert_parent): Take char argument.
+       (pinfo_fixup_after_fork): Delete declaration.
+       (hexec_proc): Ditto.
+       * sigproc.cc (remove_proc): Close pid_handle and hProcess if
+       appropriate.
+       * spawn.cc (spawn_guts): Set cygheap->pid_handle on first exec.
+
+2004-11-25  Christopher Faylor  <cgf@timesys.com>
+
+       * cygheap.h (init_cygheap::pid_handle): New element.
+       * pinfo.cc (set_myself): Clear previously existing cygheap->pid_handle
+       when a new process has been started.
+       (pinfo::wait): Make sure that a handle to the newly forked/spawned
+       process is kept around so that the pid will not be reused.
+       * pinfo.h (_pinfo::pid_handle): Move.
+       (pinfo::pid_handle): to here.
+       * spawn.cc (spawn_guts): Create a pid_handle in cygheap prior to
+       spawning to ensure that the pid does not get reused during the lifetime
+       of the "cygwin pid".
+
+2004-11-25  Christopher Faylor  <cgf@timesys.com>
+
+       * pinfo.h (pinfo::alert_parent): New function.
+       * exceptions.cc (sig_handle_tty_stop): Use alert_parent to send
+       "signals" to parent.
+       * fork.cc (fork_parent): Don't close pi.hProcess.  Let the waiter
+       thread do that.
+       * pinfo.cc (proc_waiter): Detect case where process exits without
+       setting the exit code and use value from GetExitCodeProcess.
+       Reluctantly implement __SIGREPARENT.
+       (pinfo::alert_parent): Define.
+       * sigproc.h (__SIGREPARENT): New enum.
+       * spawn.cc (spawn_guts): Send reparent signal to parent on exec.
+       Always create process in suspended state to avoid races.
+
+2004-11-25  Christopher Faylor  <cgf@timesys.com>
+
+       Remove cygthread.h in favor of cygtls.h throughout since cygtls now
+       includes cygthread.h.  Eliminate ppid_handle usage throughout.
+       * child_info.h: Regenerate magic number
+       (child_info): Remove pppid_handle.
+       * cygthread.h (cygthread::release): New method.  Frees thread without
+       waiting.
+       * cygthread.cc (cygthread::stub): Set _ctinfo in _mytls to point to
+       information for executing thread.  Don't call SetEvent if thread is no
+       longer in use.
+       (cygthread::simplestub): Ditto.
+       * cygtls.h (_cygtls::_ctinfo): New element contains pointer to
+       information about executing cygthread, if any.
+       * dcrt0.cc: Remove last vestiges of per_thread stuff.
+       (dll_crt0_0): Ditto.  Remove accommodation for ppid_handle.
+       (do_exit): Remove obsolete reparenting test.
+       (_exit): Exit with a more SUSv3-like exit value.
+       * dtable.cc (dtable::stdio_init): Check for myself->cygstarted rather
+       than myself->ppid_handle to see if we were started by a cygwin process.
+       * exceptions.cc (open_stackdumpfile): Ditto.
+       (handle_exceptions): Ditto.
+       (ctrl_c_handler): Ditto.
+       (sig_handle_tty_stop): Ditto.  Let parent send signal to itself on
+       STOP.
+       (sigpacket::process): Comment out vfork test.
+       (signal_exit): Use more SUSv3-like exit value on signal.
+       * external.cc (fillout_pinfo): Don't set hProcess.
+       * fork.cc: Remove VFORK cruft.
+       (per_thread::set): Delete.
+       (fork_child): Remove perthread stuff.
+       (fork_parent): Remove obsolete subproc_init.  Accommodate new method
+       for tracking subprocesses.
+       * pinfo.cc (set_myself): Accommodate new pinfo/_pinfo layout.  Set some
+       things here that used to be set in wait_sig.
+       (_pinfo::exit): Set exitcode here.  Close process pipe.
+       (_pinfo::commune_send): Accommodeate new pinfo/_pinfo layout.
+       (proc_waiter): New function.  Waits, in a thread for subprocess to go
+       away.
+       (pinfo::wait): New function.  Initialization for proc_waiter.
+       * pinfo.h (_pinfo::exitcode): New element.
+       (_pinfo::cygstarted): Ditto.
+       (_pinfo::wr_proc_pipe): Ditto.
+       (_pinfo::ppid_handle): Delete.
+       (_pinfo::hProcess): Delete.
+       (_pinfo::lock): Delete.
+       (pinfo::hProcess): New element.
+       (pinfo::lock): Ditto.
+       (pinfo::wait): Declare new function.
+       (pinfo::preserve): Define new function.
+       * sigproc.cc: Remove old stuff from wait_subproc thread based method.
+       (zombies): Remove.
+       (procs): New.
+       (my_parent_is_alive): Just check that the parent pid exists.
+       (mychild): Just use pinfo methods to determine if child is mine.
+       (proc_subproc): Revamp PROC_ADDCHILD to use pinfo::wait.  Remove
+       PROC_CHILDTERMINATED logic.  Use different method to remove processes
+       from list when SIGCHLD == SIG_IGN.
+       (proc_terminate): Gut.
+       (subproc_init): Delete.
+       (init_child_info): Remove setting of pppid_handle.
+       (checkstate): Revamp to only scan procs array.
+       (remove_proc): Rename from remove_zombie.  Don't close hProcess or
+       pid_handle.  Don't release memory if it's myself.
+       (stopped_or_terminated): Change logic to handle new consolidated
+       proc/zombie array.
+       (wait_subproc): Delete.
+       * sigproc.h: Remove obsolete EXIT_* defines.
+       (subproc_init): Remove declaration.
+       * spawn.cc (spawn_guts): Remove reparenting stuff.  Use standard wait
+       logic to wait for child if started from a non-cygwin process.
+       * tlsoffsets.h: Regenerate.
+       * tty.cc (tty_init): Check for myself->cygstarted rather than
+       myself->ppid_handle to see if we were started by a cygwin process.
+       * include/sys/signal.h (external_pinfo::exitcode): Replace hProcess.
+       * include/sys/wait.h (WCOREDUMP): Define.
+
+       * fhandler_tty.cc (fhandler_tty_slave::read): Add debugging output for
+       timeout case.
+       * signal.cc (abort): Flag that we are exiting with the ABORT signal.
+
 2004-11-22  Christopher Faylor  <cgf@timesys.com>
 
        * select.cc (select_stuff::test_and_set): Remove extraneous tests of
index 3088bea..7cbcb6f 100644 (file)
@@ -29,7 +29,7 @@ enum
 
 #define EXEC_MAGIC_SIZE sizeof(child_info)
 
-#define CURR_CHILD_INFO_MAGIC 0x19c16fb6U
+#define CURR_CHILD_INFO_MAGIC 0x83e9a7b7U
 
 /* NOTE: Do not make gratuitous changes to the names or organization of the
    below class.  The layout is checksummed to determine compatibility between
@@ -45,7 +45,6 @@ public:
   HANDLE subproc_ready;        // used for synchronization with parent
   HANDLE user_h;
   HANDLE parent;
-  HANDLE pppid_handle;
   init_cygheap *cygheap;
   void *cygheap_max;
   DWORD cygheap_reserve_sz;
@@ -83,7 +82,6 @@ class child_info_spawn: public child_info
 {
 public:
   cygheap_exec_info *moreinfo;
-  HANDLE hexec_proc;
 
   child_info_spawn (): moreinfo (NULL) {}
   ~child_info_spawn ()
index 9e86519..323ab0a 100644 (file)
@@ -289,6 +289,7 @@ struct init_cygheap
   size_t sthreads;
   int open_fhs;
   pid_t pid;                   /* my pid */
+  HANDLE pid_handle;           /* handle for my pid */
   void close_ctty ();
 };
 
index 7ad860b..1f071b8 100644 (file)
@@ -11,7 +11,6 @@ details. */
 #include <stdlib.h>
 #include "exceptions.h"
 #include "security.h"
-#include "cygthread.h"
 #include "sync.h"
 #include "cygerrno.h"
 #include "sigproc.h"
@@ -33,6 +32,7 @@ DWORD WINAPI
 cygthread::stub (VOID *arg)
 {
   cygthread *info = (cygthread *) arg;
+  _my_tls._ctinfo = info;
   if (info->arg == cygself)
     {
       if (info->ev)
@@ -69,7 +69,8 @@ cygthread::stub (VOID *arg)
          info->func = NULL;    // catch erroneous activation
 #endif
          info->__name = NULL;
-         SetEvent (info->ev);
+         if (info->inuse)
+           SetEvent (info->ev);
        }
       switch (WaitForSingleObject (info->thread_sync, INFINITE))
        {
@@ -88,6 +89,7 @@ DWORD WINAPI
 cygthread::simplestub (VOID *arg)
 {
   cygthread *info = (cygthread *) arg;
+  _my_tls._ctinfo = info;
   info->stack_ptr = &arg;
   info->ev = info->h;
   info->func (info->arg == cygself ? info : info->arg);
index ff174c9..dfeef90 100644 (file)
@@ -6,6 +6,9 @@ This software is a copyrighted work licensed under the terms of the
 Cygwin license.  Please consult the file "CYGWIN_LICENSE" for
 details. */
 
+#ifndef _CYGTHREAD_H
+#define _CYGTHREAD_H
+
 class cygthread
 {
   LONG inuse;
@@ -25,6 +28,7 @@ class cygthread
   static DWORD WINAPI simplestub (VOID *);
   static DWORD main_thread_id;
   static const char * name (DWORD = 0);
+  void release () { __name = NULL; inuse = false; }
   cygthread (LPTHREAD_START_ROUTINE, LPVOID, const char *);
   cygthread () {};
   static void init ();
@@ -43,3 +47,4 @@ class cygthread
 };
 
 #define cygself NULL
+#endif /*_CYGTHREAD_H*/
index 6be3881..22db636 100644 (file)
@@ -19,7 +19,6 @@ details. */
 #include "fhandler.h"
 #include "dtable.h"
 #include "cygheap.h"
-#include "cygthread.h"
 #include "pinfo.h"
 #include "sigproc.h"
 
index 016bf8c..deff108 100644 (file)
@@ -32,6 +32,8 @@ details. */
 
 #define TLS_STACK_SIZE 256
 
+#include "cygthread.h"
+
 #pragma pack(push,4)
 struct _local_storage
 {
@@ -131,6 +133,7 @@ struct _cygtls
       char __dontuse[8 * ((sizeof(struct _reent) + 4) / 8)];
     };
   struct _local_storage locals;
+  class cygthread *_ctinfo;
   waitq wq;
   struct _cygtls *prev, *next;
   __stack_t *stackptr;
index 47cd8b1..51b197e 100644 (file)
@@ -29,11 +29,10 @@ details. */
 #include "dtable.h"
 #include "cygheap.h"
 #include "child_info_magic.h"
-#include "perthread.h"
+#include "cygtls.h"
 #include "shared_info.h"
 #include "cygwin_version.h"
 #include "dll_init.h"
-#include "cygthread.h"
 #include "sync.h"
 #include "heap.h"
 
@@ -44,16 +43,6 @@ details. */
 HANDLE NO_COPY hMainProc = (HANDLE) -1;
 HANDLE NO_COPY hMainThread;
 
-#ifdef NEWVFORK
-per_thread_vfork NO_COPY vfork_storage;
-#endif
-
-per_thread NO_COPY *threadstuff[] = {
-#ifdef NEWVFORK
-                                    &vfork_storage,
-#endif
-                                    NULL};
-
 bool display_title;
 bool strip_title_path;
 bool allow_glob = true;
@@ -656,8 +645,6 @@ dll_crt0_0 ()
     memory_init ();
   else
     {
-      bool close_ppid_handle = false;
-      bool close_hexec_proc = false;
       switch (child_proc_info->type)
        {
          case _PROC_FORK:
@@ -665,16 +652,9 @@ dll_crt0_0 ()
            cygheap_fixup_in_child (false);
            memory_init ();
            set_myself (NULL);
-           close_ppid_handle = !!child_proc_info->pppid_handle;
            break;
          case _PROC_SPAWN:
-           /* Have to delay closes until after cygheap is setup */
-           close_hexec_proc = !!spawn_info->hexec_proc;
-           close_ppid_handle = !!child_proc_info->pppid_handle;
-           goto around;
          case _PROC_EXEC:
-           hexec_proc = spawn_info->hexec_proc;
-         around:
            HANDLE h;
            cygheap_fixup_in_child (true);
            memory_init ();
@@ -697,10 +677,6 @@ dll_crt0_0 ()
              }
            break;
        }
-      if (close_hexec_proc)
-       CloseHandle (spawn_info->hexec_proc);
-      if (close_ppid_handle)
-       CloseHandle (child_proc_info->pppid_handle);
     }
 
   _cygtls::init ();
@@ -1014,13 +990,10 @@ do_exit (int status)
   if (exit_state < ES_SIGNAL)
     {
       exit_state = ES_SIGNAL;
-      if (!(n & EXIT_REPARENTING))
-       {
-         signal (SIGCHLD, SIG_IGN);
-         signal (SIGHUP, SIG_IGN);
-         signal (SIGINT, SIG_IGN);
-         signal (SIGQUIT, SIG_IGN);
-       }
+      signal (SIGCHLD, SIG_IGN);
+      signal (SIGHUP, SIG_IGN);
+      signal (SIGINT, SIG_IGN);
+      signal (SIGQUIT, SIG_IGN);
     }
 
   if (exit_state < ES_CLOSEALL)
@@ -1112,7 +1085,7 @@ cygwin_exit (int n)
 extern "C" void
 _exit (int n)
 {
-  do_exit ((DWORD) n & 0xffff);
+  do_exit (((DWORD) n & 0xff) << 8);
 }
 
 extern "C" void
index db5da1a..7411a5d 100644 (file)
@@ -11,7 +11,6 @@ details. */
 #include "sync.h"
 #include "sigproc.h"
 #include "pinfo.h"
-#include "perthread.h"
 #include "perprocess.h"
 #include "security.h"
 #include "cygerrno.h"
index cc72a2a..81c84a9 100644 (file)
@@ -140,7 +140,7 @@ dtable::stdio_init ()
      Also, always set them even if we're to pick up our parent's fds
      in case they're missed.  */
 
-  if (myself->ppid_handle || ISSTATE (myself, PID_CYGPARENT))
+  if (myself->cygstarted || ISSTATE (myself, PID_CYGPARENT))
     return;
 
   HANDLE in = GetStdHandle (STD_INPUT_HANDLE);
index 510f534..bc28cc8 100644 (file)
@@ -20,12 +20,9 @@ details. */
 #include "cygtls.h"
 #include "sigproc.h"
 #include "cygerrno.h"
-#define NEED_VFORK
-#include "perthread.h"
 #include "shared_info.h"
 #include "perprocess.h"
 #include "security.h"
-#include "cygthread.h"
 
 #define CALL_HANDLER_RETRY 20
 
@@ -159,7 +156,7 @@ open_stackdumpfile ()
                             CREATE_ALWAYS, 0, 0);
       if (h != INVALID_HANDLE_VALUE)
        {
-         if (!myself->ppid_handle)
+         if (!myself->cygstarted)
            system_printf ("Dumping stack trace to %s", corefile);
          else
            debug_printf ("Dumping stack trace to %s", corefile);
@@ -514,7 +511,7 @@ handle_exceptions (EXCEPTION_RECORD *e0, void *frame, CONTEXT *in0, void *)
       || (void *) global_sigs[si.si_signo].sa_handler == (void *) SIG_ERR)
     {
       /* Print the exception to the console */
-      if (!myself->ppid_handle)
+      if (!myself->cygstarted)
        for (int i = 0; status_info[i].name; i++)
          if (status_info[i].code == e.ExceptionCode)
            {
@@ -596,31 +593,15 @@ sig_handle_tty_stop (int sig)
   _my_tls.incyg = 1;
   /* Silently ignore attempts to suspend if there is no accommodating
      cygwin parent to deal with this behavior. */
-  if (!myself->ppid_handle)
+  if (!myself->cygstarted)
     {
       myself->process_state &= ~PID_STOPPED;
       return;
     }
 
   myself->stopsig = sig;
-  /* See if we have a living parent.  If so, send it a special signal.
-     It will figure out exactly which pid has stopped by scanning
-     its list of subprocesses.  */
-  if (my_parent_is_alive ())
-    {
-      pinfo parent (myself->ppid);
-      if (NOTSTATE (parent, PID_NOCLDSTOP))
-       {
-         siginfo_t si;
-         si.si_signo = SIGCHLD;
-         si.si_code = SI_KERNEL;
-         si.si_sigval.sival_int = CLD_STOPPED;
-         si.si_errno = si.si_pid = si.si_uid = si.si_errno = 0;
-         sig_send (parent, si);
-       }
-    }
-  sigproc_printf ("process %d stopped by signal %d, myself->ppid_handle %p",
-                 myself->pid, sig, myself->ppid_handle);
+  myself.alert_parent (sig);
+  sigproc_printf ("process %d stopped by signal %d", myself->pid, sig);
   HANDLE w4[2];
   w4[0] = sigCONT;
   w4[1] = signal_arrived;
@@ -629,6 +610,7 @@ sig_handle_tty_stop (int sig)
     case WAIT_OBJECT_0:
     case WAIT_OBJECT_0 + 1:
       reset_signal_arrived ();
+      myself.alert_parent (SIGCONT);
       break;
     default:
       api_fatal ("WaitSingleObject failed, %E");
@@ -807,7 +789,7 @@ ctrl_c_handler (DWORD type)
 
   if (!cygwin_finished_initializing)
     {
-      if (myself->ppid_handle) /* Was this process created by a cygwin process? */
+      if (myself->cygstarted)  /* Was this process created by a cygwin process? */
        return TRUE;            /* Yes.  Let the parent eventually handle CTRL-C issues. */
       debug_printf ("exiting with status %p", STATUS_CONTROL_C_EXIT);
       ExitProcess (STATUS_CONTROL_C_EXIT);
@@ -982,7 +964,7 @@ sigpacket::process ()
   bool special_case;
   bool insigwait_mask;
   insigwait_mask = masked = false;
-  if (special_case = (VFORKPID || ISSTATE (myself, PID_STOPPED)))
+  if (special_case = (/*VFORKPID || */ISSTATE (myself, PID_STOPPED)))
     /* nothing to do */;
   else if (tls && sigismember (&tls->sigwait_mask, si.si_signo))
     insigwait_mask = true;
@@ -1097,7 +1079,6 @@ static void
 signal_exit (int rc)
 {
   EnterCriticalSection (&exit_lock);
-  rc = EXIT_SIGNAL | (rc << 8);
   if (exit_already++)
     myself->exit (rc);
 
index c0cad36..56ef0c6 100644 (file)
@@ -25,7 +25,6 @@ details. */
 #include "cygheap.h"
 #include "wincap.h"
 #include "heap.h"
-#include "cygthread.h"
 #include "pwdgrp.h"
 #include "cygtls.h"
 
@@ -72,7 +71,6 @@ fillout_pinfo (pid_t pid, int winpid)
          ep.ctty = p->ctty;
          ep.pid = p->pid;
          ep.ppid = p->ppid;
-         ep.hProcess = p->hProcess;
          ep.dwProcessId = p->dwProcessId;
          ep.uid = p->uid;
          ep.gid = p->gid;
index 81f495f..76b7911 100644 (file)
@@ -28,7 +28,6 @@ details. */
 #include "sigproc.h"
 #include "pinfo.h"
 #include "shared_info.h"
-#include "cygthread.h"
 #include "cygtls.h"
 
 #define CONVERT_LIMIT 16384
index c64aac7..642f5ca 100644 (file)
@@ -771,7 +771,10 @@ fhandler_tty_slave::read (void *ptr, size_t& len)
       rc = WaitForMultipleObjects (2, w4, FALSE, waiter);
 
       if (rc == WAIT_TIMEOUT)
-       break;
+       {
+         termios_printf ("wait timed out, waiter %u", waiter);
+         break;
+       }
 
       if (rc == WAIT_FAILED)
        {
index 187fcdc..1dc1e7b 100644 (file)
@@ -22,8 +22,7 @@ details. */
 #include "pinfo.h"
 #include "cygheap.h"
 #include "child_info.h"
-#define NEED_VFORK
-#include "perthread.h"
+#include "cygtls.h"
 #include "perprocess.h"
 #include "dll_init.h"
 #include "sync.h"
@@ -42,17 +41,6 @@ details. */
 #define dll_bss_start &_bss_start__
 #define dll_bss_end &_bss_end__
 
-void
-per_thread::set (void *s)
-{
-  if (s == PER_THREAD_FORK_CLEAR)
-    {
-      tls = TlsAlloc ();
-      s = NULL;
-    }
-  TlsSetValue (get_tls (), s);
-}
-
 static void
 stack_base (child_info_fork &ch)
 {
@@ -296,7 +284,6 @@ fork_child (HANDLE& hParent, dll *&first_dll, bool& load_dlls)
   (void) ForceCloseHandle1 (fork_info->subproc_ready, subproc_ready);
   (void) ForceCloseHandle1 (fork_info->forker_finished, forker_finished);
 
-  pinfo_fixup_after_fork ();
   _my_tls.fixup_after_fork ();
   sigproc_init ();
 
@@ -305,13 +292,6 @@ fork_child (HANDLE& hParent, dll *&first_dll, bool& load_dlls)
     api_fatal ("recreate_shm areas after fork failed");
 #endif
 
-  /* Set thread local stuff to zero.  Under Windows 95/98 this is sometimes
-     non-zero, for some reason.
-     FIXME:  There is a memory leak here after a fork. */
-  for (per_thread **t = threadstuff; *t; t++)
-    if ((*t)->clear_on_fork ())
-      (*t)->set ();
-
   pthread::atforkchild ();
   fixup_timers_after_fork ();
   cygbench ("fork-child");
@@ -356,8 +336,6 @@ fork_parent (HANDLE& hParent, dll *&first_dll,
 
   pthread::atforkprepare ();
 
-  subproc_init ();
-
   int c_flags = GetPriorityClass (hMainProc) /*|
                CREATE_NEW_PROCESS_GROUP*/;
   STARTUPINFO si = {0, NULL, NULL, NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL};
@@ -384,7 +362,7 @@ fork_parent (HANDLE& hParent, dll *&first_dll,
   /* Create an inheritable handle to pass to the child process.  This will
      allow the child to duplicate handles from the parent to itself. */
   hParent = NULL;
-  if (!DuplicateHandle (hMainProc, hMainProc, hMainProc, &hParent, 0, 1,
+  if (!DuplicateHandle (hMainProc, hMainProc, hMainProc, &hParent, 0, TRUE,
                        DUPLICATE_SAME_ACCESS))
     {
       system_printf ("couldn't create handle to myself for child, %E");
@@ -501,8 +479,8 @@ fork_parent (HANDLE& hParent, dll *&first_dll,
   ProtectHandle1 (pi.hProcess, childhProc);
 
   /* Fill in fields in the child's process table entry.  */
-  forked->hProcess = pi.hProcess;
   forked->dwProcessId = pi.dwProcessId;
+  forked.hProcess = pi.hProcess;
 
   /* Hopefully, this will succeed.  The alternative to doing things this
      way is to reserve space prior to calling CreateProcess and then fill
index 2b42462..b8c9973 100644 (file)
@@ -232,7 +232,7 @@ struct external_pinfo
   {
   pid_t pid;
   pid_t ppid;
-  HANDLE hProcess;
+  DWORD exitcode;
   DWORD dwProcessId, dwSpawnedProcessId;
   __uid16_t uid;
   __gid16_t gid;
index 9dd8bf7..d070838 100644 (file)
@@ -1,6 +1,6 @@
 /* sys/wait.h
 
-   Copyright 1997, 1998, 2001 Red Hat, Inc.
+   Copyright 1997, 1998, 2001, 2002, 2003, 2004 Red Hat, Inc.
 
 This file is part of Cygwin.
 
@@ -36,6 +36,7 @@ extern "C" {
 #define WEXITSTATUS(w) (((w) >> 8) & 0xff)
 #define WTERMSIG(w)    ((w) & 0x7f)
 #define WSTOPSIG       WEXITSTATUS
+#define WCOREDUMP(w)   (WIFSIGNALED(w) && (w & 0x80))
 
 pid_t wait (int *);
 pid_t waitpid (pid_t, int *, int);
index cc86870..7ba0dc3 100644 (file)
@@ -12,7 +12,6 @@ details. */
 #include <stdlib.h>
 #include "thread.h"
 #include "perprocess.h"
-#include "cygthread.h"
 #include "cygtls.h"
 
 int NO_COPY dynamically_loaded;
diff --git a/winsup/cygwin/perthread.h b/winsup/cygwin/perthread.h
deleted file mode 100644 (file)
index e10a624..0000000
+++ /dev/null
@@ -1,86 +0,0 @@
-/* perthread.h: Header file for cygwin thread-local storage.
-
-   Copyright 2000, 2001, 2002, 2003, 2004 Red Hat, Inc.
-
-   Written by Christopher Faylor <cgf@cygnus.com>
-
-This file is part of Cygwin.
-
-This software is a copyrighted work licensed under the terms of the
-Cygwin license.  Please consult the file "CYGWIN_LICENSE" for
-details. */
-
-#define PTMAGIC 0x77366377
-
-#define PER_THREAD_FORK_CLEAR ((void *)UINT32_MAX)
-class per_thread
-{
-  DWORD tls;
-  int clear_on_fork_p;
-public:
-  per_thread (int forkval = 1) {tls = TlsAlloc (); clear_on_fork_p = forkval;}
-  DWORD get_tls () {return tls;}
-  int clear_on_fork () {return clear_on_fork_p;}
-
-  virtual void *get () {return TlsGetValue (get_tls ());}
-  virtual size_t size () {return 0;}
-  virtual void set (void *s = NULL);
-  virtual void set (int n) {TlsSetValue (get_tls (), (void *)n);}
-  virtual void *create ()
-  {
-    void *s = calloc (1, size ());
-    set (s);
-    return s;
-  }
-};
-
-#ifdef NEED_VFORK
-#include "cygtls.h"
-#endif
-
-#ifndef NEWVFORK
-#define VFORKPID 0
-#else
-#if defined (NEED_VFORK)
-class vfork_save
-{
-  jmp_buf j;
-  int exitval;
- public:
-  int pid;
-  DWORD frame[100];
-  _cygtls tls;
-  char **vfork_ebp;
-  char **vfork_esp;
-  int ctty;
-  pid_t sid;
-  pid_t pgid;
-  int open_fhs;
-  int is_active () { return pid < 0; }
-  void restore_pid (int val)
-  {
-    pid = val;
-    longjmp (j, 1);
-  }
-  void restore_exit (int val)
-  {
-    exitval = val;
-    longjmp (j, 1);
-  }
-  friend int vfork ();
-};
-
-class per_thread_vfork : public per_thread
-{
-public:
-  vfork_save *val () { return (vfork_save *) per_thread::get (); }
-  vfork_save *create () {return (vfork_save *) per_thread::create ();}
-  size_t size () {return sizeof (vfork_save);}
-};
-extern per_thread_vfork vfork_storage;
-extern vfork_save *main_vfork;
-#define VFORKPID main_vfork->pid
-#endif
-#endif /*NEWVFORK*/
-
-extern per_thread *threadstuff[];
index 829db2a..8a42daa 100644 (file)
@@ -24,9 +24,9 @@ details. */
 #include "perprocess.h"
 #include "environ.h"
 #include <assert.h>
+#include <sys/wait.h>
 #include <ntdef.h>
 #include "ntdll.h"
-#include "cygthread.h"
 #include "shared_info.h"
 #include "cygheap.h"
 #include "fhandler.h"
@@ -37,23 +37,6 @@ static char NO_COPY pinfo_dummy[sizeof (_pinfo)] = {0};
 
 pinfo NO_COPY myself ((_pinfo *)&pinfo_dummy); // Avoid myself != NULL checks
 
-HANDLE hexec_proc;
-
-void __stdcall
-pinfo_fixup_after_fork ()
-{
-  if (hexec_proc)
-    CloseHandle (hexec_proc);
-  /* Keeps the cygpid from being reused.  No rights required */
-  if (!DuplicateHandle (hMainProc, hMainProc, hMainProc, &hexec_proc, 0,
-                       TRUE, 0))
-    {
-      system_printf ("couldn't save current process handle %p, %E", hMainProc);
-      hexec_proc = NULL;
-    }
-  VerifyHandle (hexec_proc);
-}
-
 /* Initialize the process table.
    This is done once when the dll is first loaded.  */
 
@@ -70,7 +53,30 @@ set_myself (HANDLE h)
   if (!strace.active)
     strace.hello ();
   debug_printf ("myself->dwProcessId %u", myself->dwProcessId);
-  InitializeCriticalSection (&myself->lock);
+  InitializeCriticalSection (&myself.lock);
+  myself->dwProcessId = GetCurrentProcessId ();
+  if (h)
+    {
+      /* here if execed */
+      static pinfo NO_COPY myself_identity;
+      myself_identity.init (cygwin_pid (myself->dwProcessId), PID_EXECED);
+    }
+  else if (myself->ppid)
+    {
+      /* here if forked/spawned */
+      pinfo parent (myself->ppid);
+      /* We've inherited the parent's wr_proc_pipe.  We don't need it,
+        so close it.  This could cause problems for the spawn case since there
+        is no guarantee that a parent will still be around by the time we get
+        here.  If so, we would have a handle leak.  FIXME?  */
+      if (parent && parent->wr_proc_pipe)
+       CloseHandle (parent->wr_proc_pipe);
+      if (cygheap->pid_handle)
+       {
+         ForceCloseHandle (cygheap->pid_handle);
+         cygheap->pid_handle = NULL;
+       }
+    }
   return;
 }
 
@@ -107,17 +113,27 @@ _pinfo::exit (UINT n, bool norecord)
   exit_state = ES_FINAL;
   cygthread::terminate ();
   if (norecord)
-    sigproc_terminate ();
+    sigproc_terminate ();      /* Just terminate signal and process stuff */
+  else
+    exitcode = n;              /* We're really exiting.  Record the UNIX exit code. */
+
   if (this)
     {
-      if (!norecord)
-       process_state = PID_EXITED;
-
       /* FIXME:  There is a potential race between an execed process and its
         parent here.  I hated to add a mutex just for this, though.  */
       struct rusage r;
       fill_rusage (&r, hMainProc);
       add_rusage (&rusage_self, &r);
+
+      if (!norecord)
+       {
+         process_state = PID_EXITED;
+         /* We could just let this happen automatically when the process
+            exits but this should gain us a microsecond or so by notifying
+            the parent early.  */
+         if (wr_proc_pipe)
+           CloseHandle (wr_proc_pipe);
+       }
     }
 
   sigproc_printf ("Calling ExitProcess %d", n);
@@ -259,6 +275,7 @@ pinfo::init (pid_t n, DWORD flag, HANDLE in_h)
          procinfo->process_state |= PID_IN_USE | PID_EXECED;
          procinfo->pid = myself->pid;
        }
+
       break;
     }
   destroy = 1;
@@ -505,7 +522,7 @@ _pinfo::commune_send (DWORD code, ...)
       __seterrno ();
       goto err;
     }
-  EnterCriticalSection (&myself->lock);
+  EnterCriticalSection (&myself.lock);
   myself->tothem = tome;
   myself->fromthem = fromme;
   myself->hello_pid = pid;
@@ -609,7 +626,7 @@ err:
 
 out:
   myself->hello_pid = 0;
-  LeaveCriticalSection (&myself->lock);
+  LeaveCriticalSection (&myself.lock);
   return res;
 }
 
@@ -642,6 +659,196 @@ _pinfo::cmdline (size_t& n)
   return s;
 }
 
+/* This is the workhorse which waits for the write end of the pipe
+   created during new process creation.  If the pipe is closed, it is
+   assumed that the cygwin pid has exited.  Otherwise, various "signals"
+   can be sent to the parent to inform the parent to perform a certain
+   action.
+
+   This code was originally written to eliminate the need for "reparenting"
+   but, unfortunately, reparenting is still needed in order to get the
+   exit code of an execed windows process.  Otherwise, the exit code of
+   a cygwin process comes from the exitcode field in _pinfo. */
+static DWORD WINAPI
+proc_waiter (void *arg)
+{
+  extern HANDLE hExeced;
+  pinfo& vchild = *(pinfo *) arg;
+
+  siginfo_t si;
+  si.si_signo = SIGCHLD;
+  si.si_code = SI_KERNEL;
+  si.si_pid = vchild->pid;
+  si.si_errno = 0;
+#if 0  // FIXME: This is tricky to get right
+  si.si_utime = pchildren[rc]->rusage_self.ru_utime;
+  si.si_stime = pchildren[rc].rusage_self.ru_stime;
+#else
+  si.si_utime = 0;
+  si.si_stime = 0;
+#endif
+  pid_t pid = vchild->pid;
+
+  for (;;)
+    {
+      DWORD nb;
+      char buf = '\0';
+      if (!ReadFile (vchild.rd_proc_pipe, &buf, 1, &nb, NULL)
+         && GetLastError () != ERROR_BROKEN_PIPE)
+       {
+         system_printf ("error on read of child wait pipe %p, %E", vchild.rd_proc_pipe);
+         break;
+       }
+
+      si.si_uid = vchild->uid;
+
+      switch (buf)
+       {
+       case 0:
+         /* Child exited.  Do some cleanup and signal myself.  */
+         CloseHandle (vchild.rd_proc_pipe);
+         vchild.rd_proc_pipe = NULL;
+
+         if (vchild->process_state != PID_EXITED && vchild.hProcess)
+           {
+             DWORD exit_code;
+             if (GetExitCodeProcess (vchild.hProcess, &exit_code))
+               vchild->exitcode = (exit_code & 0xff) << 8;
+           }
+         if (WIFEXITED (vchild->exitcode))
+           si.si_sigval.sival_int = CLD_EXITED;
+         else if (WCOREDUMP (vchild->exitcode))
+           si.si_sigval.sival_int = CLD_DUMPED;
+         else
+           si.si_sigval.sival_int = CLD_KILLED;
+         si.si_status = vchild->exitcode;
+         vchild->process_state = PID_ZOMBIE;
+         break;
+       case SIGTTIN:
+       case SIGTTOU:
+       case SIGTSTP:
+       case SIGSTOP:
+         /* Child stopped.  Signal myself.  */
+         si.si_sigval.sival_int = CLD_STOPPED;
+         break;
+       case SIGCONT:
+         continue;
+       case __SIGREPARENT: /* sigh */
+         /* spawn_guts has signalled us that it has just started a new
+            subprocess which will take over this cygwin pid.  */
+
+         /* We need to keep a handle to the original windows process which
+            represents the cygwin process around to make sure that the
+            windows pid is not reused before we are through with it.
+            So, detect the first time that a subprocess calls exec
+            and save the current hprocess in the pid_handle field.
+            On subsequent execs just close the handle. */
+         if (!vchild.hProcess)
+           /* something went wrong.  oh well. */;
+         else if (vchild.pid_handle)
+           ForceCloseHandle1 (vchild.hProcess, childhProc);
+         else
+           vchild.pid_handle = vchild.hProcess;
+         vchild.hProcess = OpenProcess (PROCESS_QUERY_INFORMATION, FALSE,
+                                        vchild->dwProcessId);
+         vchild->cygstarted++;
+         if (vchild.hProcess)
+           ProtectHandle1 (vchild.hProcess, childhProc);
+         continue;
+       default:
+         system_printf ("unknown value %d on proc pipe", buf);
+         continue;
+       }
+
+      /* Special case:  If the "child process" that died is us, then we're
+        execing.  Just call proc_subproc directly and then exit this loop.
+        We're done here.  */
+      if (hExeced && vchild->pid == myself->pid)
+       {
+         /* execing.  no signals available now. */
+         proc_subproc (PROC_CLEARWAIT, 0);
+         break;
+       }
+
+      /* Send a SIGCHLD to myself.   We do this here, rather than in proc_subproc
+        to avoid the proc_subproc lock since the signal thread will eventually
+        be calling proc_subproc and could unnecessarily block. */
+      sig_send (myself_nowait, si);
+
+      /* If we're just stopped or got a continue signal, keep looping.
+        Otherwise, return this thread to the pool. */
+      if (buf != '\0')
+       sigproc_printf ("looping");
+      else
+       break;
+    }
+
+  sigproc_printf ("exiting wait thread for pid %d", pid);
+  _my_tls._ctinfo->release (); /* return the cygthread to the cygthread pool */
+  return 0;
+}
+
+/* function to set up the process pipe and kick off proc_waiter */
+int
+pinfo::wait ()
+{
+  HANDLE out;
+  /* FIXME: execed processes should be able to wait for pids that were started
+     by the process which execed them. */
+  if (!CreatePipe (&rd_proc_pipe, &out, &sec_none_nih, 16))
+    {
+      system_printf ("Couldn't create pipe tracker for pid %d, %E",
+                    (*this)->pid);
+      return 0;
+    }
+  /* Duplicate the write end of the pipe into the subprocess.  Make it inheritable
+     so that all of the execed children get it.  */
+  if (!DuplicateHandle (hMainProc, out, hProcess, &((*this)->wr_proc_pipe), 0,
+                       TRUE, DUPLICATE_SAME_ACCESS))
+    {
+      system_printf ("Couldn't duplicate pipe topid %d(%p), %E", (*this)->pid,
+                    hProcess);
+      return 0;
+    }
+  CloseHandle (out);   /* Don't need this end in this proces */
+
+  preserve ();         /* Preserve the shared memory associated with the pinfo */
+
+  /* Fire up a new thread to track the subprocess */
+  cygthread *h = new cygthread (proc_waiter, this, "sig");
+  if (!h)
+    sigproc_printf ("tracking thread creation failed for pid %d", (*this)->pid);
+  else
+    {
+      h->zap_h ();
+      sigproc_printf ("created tracking thread for pid %d, winpid %p, rd_pipe %p",
+                     (*this)->pid, (*this)->dwProcessId, rd_proc_pipe);
+    }
+
+  return 1;
+}
+
+/* function to send a "signal" to the parent when something interesting happens
+   in the child. */
+void
+pinfo::alert_parent (char sig)
+{
+  DWORD nb;
+  /* Send something to our parent.  If the parent has gone away,
+     close the pipe. */
+  if (myself->wr_proc_pipe
+      && WriteFile (myself->wr_proc_pipe, &sig, 1, &nb, NULL))
+    /* all is well */;
+  else if (GetLastError () != ERROR_BROKEN_PIPE)
+    debug_printf ("sending %d notification to parent failed, %E", sig);
+  else
+    {
+      HANDLE closeit = myself->wr_proc_pipe;
+      myself->wr_proc_pipe = NULL;
+      CloseHandle (closeit);
+    }
+}
+
 void
 pinfo::release ()
 {
index aa1fb8c..b062934 100644 (file)
@@ -36,19 +36,12 @@ public:
      constants below. */
   DWORD process_state;
 
-  /* If hProcess is set, it's because it came from a
-     CreateProcess call.  This means it's process relative
-     to the thing which created the process.  That's ok because
-     we only use this handle from the parent. */
-  HANDLE hProcess;
-
-#define PINFO_REDIR_SIZE ((char *) &myself.procinfo->hProcess - (char *) myself.procinfo)
+  DWORD exitcode;      /* set when process exits */
 
-  /* Handle associated with initial Windows pid which started it all. */
-  HANDLE pid_handle;
+#define PINFO_REDIR_SIZE ((char *) &myself.procinfo->exitcode - (char *) myself.procinfo)
 
-  /* Handle to the logical parent of this pid. */
-  HANDLE ppid_handle;
+  /* > 0 if started by a cygwin process */
+  DWORD cygstarted;
 
   /* Parent process id.  */
   pid_t ppid;
@@ -120,7 +113,9 @@ public:
   HANDLE sendsig;
 private:
   sigset_t sig_mask;
-  CRITICAL_SECTION lock;
+public:
+  HANDLE wr_proc_pipe;
+  friend class pinfo;
 };
 
 class pinfo
@@ -129,12 +124,18 @@ class pinfo
   _pinfo *procinfo;
   bool destroy;
 public:
+  HANDLE rd_proc_pipe;
+  HANDLE hProcess;
+  CRITICAL_SECTION lock;
+  /* Handle associated with initial Windows pid which started it all. */
+  HANDLE pid_handle;
   void init (pid_t, DWORD, HANDLE = NULL) __attribute__ ((regparm(3)));
   pinfo () {}
-  pinfo (_pinfo *x): procinfo (x) {}
-  pinfo (pid_t n) {init (n, 0);}
-  pinfo (pid_t n, DWORD flag) {init (n, flag);}
+  pinfo (_pinfo *x): procinfo (x), hProcess (NULL), pid_handle (NULL) {}
+  pinfo (pid_t n) : rd_proc_pipe (NULL), hProcess (NULL), pid_handle (NULL) {init (n, 0);}
+  pinfo (pid_t n, DWORD flag) : rd_proc_pipe (NULL), hProcess (NULL), pid_handle (NULL)  {init (n, flag);}
   void release ();
+  int wait () __attribute__ ((regparm (1)));
   ~pinfo ()
   {
     if (destroy && procinfo)
@@ -151,6 +152,8 @@ public:
   _pinfo *operator * () const {return procinfo;}
   operator _pinfo * () const {return procinfo;}
   // operator bool () const {return (int) h;}
+  void preserve () { destroy = false; }
+  void alert_parent (char);
 #ifndef _SIGPROC_H
   int remember () {system_printf ("remember is not here"); return 0;}
 #else
@@ -210,9 +213,6 @@ extern pinfo myself;
 #define _P_VFORK 0
 #define _P_SYSTEM 512
 
-extern void __stdcall pinfo_fixup_after_fork ();
-extern HANDLE hexec_proc;
-
 /* For mmaps across fork(). */
 int __stdcall fixup_mmaps_after_fork (HANDLE parent);
 /* for shm areas across fork (). */
index a0dc131..c943b2a 100644 (file)
@@ -36,9 +36,7 @@ details. */
 #include "dtable.h"
 #include "cygheap.h"
 #include "sigproc.h"
-#include "perthread.h"
 #include "tty.h"
-#include "cygthread.h"
 #include "ntdll.h"
 #include "cygtls.h"
 #include <asm/byteorder.h>
@@ -209,7 +207,7 @@ select_stuff::test_and_set (int i, fd_set *readfds, fd_set *writefds,
   if (s->read_ready || s->write_ready || s->except_ready)
     always_ready = true;
 
-  if (s->windows_handle || s->windows_handle || s->windows_handle)
+  if (s->windows_handle)
     windows_used = true;
 
   s->next = start.next;
index bd75dff..f57e0d0 100644 (file)
@@ -342,7 +342,7 @@ abort (void)
 
   raise (SIGABRT);
   (void) _my_tls.call_signal_handler (); /* Call any signal handler */
-  do_exit (1); /* signal handler didn't exit.  Goodbye. */
+  do_exit (SIGABRT);   /* signal handler didn't exit.  Goodbye. */
 }
 
 extern "C" int
index 416761e..844e80a 100644 (file)
@@ -28,10 +28,8 @@ details. */
 #include "cygheap.h"
 #include "child_info_magic.h"
 #include "shared_info.h"
-#include "cygthread.h"
 #include "cygtls.h"
 #include "sigproc.h"
-#include "perthread.h"
 #include "exceptions.h"
 
 /*
@@ -42,11 +40,9 @@ details. */
 
 #define PSIZE 63               // Number of processes
 
-#define wake_wait_subproc() SetEvent (events[0])
-
 #define no_signals_available() (!hwait_sig || (myself->sendsig == INVALID_HANDLE_VALUE) || exit_state)
 
-#define NZOMBIES       256
+#define NPROCS 256
 
 /*
  * Global variables
@@ -64,30 +60,15 @@ HANDLE NO_COPY signal_arrived;              // Event signaled when a signal has
 
 #define Static static NO_COPY
 
-/* How long to wait for message/signals.  Normally this is infinite.
-  On termination, however, these are set to zero as a flag to exit.  */
-
-Static DWORD proc_loop_wait = 1000;    // Wait for subprocesses to exit
-
 HANDLE NO_COPY sigCONT;                        // Used to "STOP" a process
 Static cygthread *hwait_sig;           // Handle of wait_sig thread
-Static cygthread *hwait_subproc;       // Handle of sig_subproc thread
 
 Static HANDLE wait_sig_inited;         // Control synchronization of
                                        //  message queue startup
 
-/* Used by WaitForMultipleObjects.  These are handles to child processes.
- */
-Static HANDLE events[PSIZE + 1];         // All my children's handles++
-#define hchildren (events + 1)         // Where the children handles begin
-Static int nchildren;                  // Number of active children
-Static char cpchildren[PSIZE * sizeof (pinfo)];                // All my children info
-Static int nzombies;                   // Number of deceased children
-Static char czombies[(NZOMBIES + 1) * sizeof (pinfo)];         // All my deceased children info
-
-#define pchildren ((pinfo *) cpchildren)
-#define zombies ((pinfo *) czombies)
-
+Static int nprocs;                     // Number of deceased children
+Static char cprocs[(NPROCS + 1) * sizeof (pinfo)];             // All my deceased children info
+#define procs ((pinfo *) cprocs)
 Static waitq waitq_head = {0, 0, 0, 0, 0, 0, 0};// Start of queue for wait'ing threads
 
 muto NO_COPY *sync_proc_subproc = NULL;        // Control access to subproc stuff
@@ -97,9 +78,8 @@ DWORD NO_COPY sigtid = 0;             // ID of the signal thread
 /* Function declarations */
 static int __stdcall checkstate (waitq *) __attribute__ ((regparm (1)));
 static __inline__ bool get_proc_lock (DWORD, DWORD);
-static void __stdcall remove_zombie (int);
-static int __stdcall stopped_or_terminated (waitq *, _pinfo *);
-static DWORD WINAPI wait_subproc (VOID *);
+static bool __stdcall remove_proc (int);
+static bool __stdcall stopped_or_terminated (waitq *, _pinfo *);
 static DWORD WINAPI wait_sig (VOID *arg);
 
 /* wait_sig bookkeeping */
@@ -152,33 +132,13 @@ bool __stdcall
 my_parent_is_alive ()
 {
   bool res;
-  if (!myself->ppid_handle)
+  if (myself->cygstarted)
+    res = pid_exists (myself->ppid);
+  else
     {
-      debug_printf ("No myself->ppid_handle");
+      debug_printf ("Not started by cygwin app");
       res = false;
     }
-  else
-    for (int i = 0; i < 2; i++)
-      switch (res = WaitForSingleObject (myself->ppid_handle, 0))
-       {
-         case WAIT_OBJECT_0:
-           debug_printf ("parent dead.");
-           res = false;
-           goto out;
-         case WAIT_TIMEOUT:
-           debug_printf ("parent still alive");
-           res = true;
-           goto out;
-         case WAIT_FAILED:
-           DWORD werr = GetLastError ();
-           if (werr == ERROR_INVALID_HANDLE && i == 0)
-             continue;
-           system_printf ("WFSO for myself->ppid_handle(%p) failed, error %d",
-                          myself->ppid_handle, werr);
-           res = false;
-           goto out;
-       }
-out:
   return res;
 }
 
@@ -193,7 +153,7 @@ wait_for_sigthread ()
 }
 
 /* Get the sync_proc_subproc muto to control access to
- * children, zombie arrays.
+ * children, proc arrays.
  * Attempt to handle case where process is exiting as we try to grab
  * the mutex.
  */
@@ -260,16 +220,11 @@ proc_exists (_pinfo *p)
 /* Return 1 if this is one of our children, zero otherwise.
    FIXME: This really should be integrated with the rest of the proc_subproc
    testing.  Scanning these lists twice is inefficient. */
-int __stdcall
+bool __stdcall
 mychild (int pid)
 {
-  for (int i = 0; i < nchildren; i++)
-    if (pchildren[i]->pid == pid)
-      return 1;
-  for (int i = 0; i < nzombies; i++)
-    if (zombies[i]->pid == pid)
-      return 1;
-  return 0;
+  pinfo p (pid);
+  return p && p->ppid == myself->pid;
 }
 
 /* Handle all subprocess requests
@@ -283,7 +238,6 @@ proc_subproc (DWORD what, DWORD val)
   _pinfo *child;
   int clearing;
   waitq *w;
-  int thiszombie;
 
 #define wval    ((waitq *) val)
 
@@ -301,84 +255,32 @@ proc_subproc (DWORD what, DWORD val)
      * (usually called from the main thread)
      */
     case PROC_ADDCHILD:
-      if (nchildren >= PSIZE - 1)
+      /* Filled up process table? */
+      if (nprocs >= NPROCS)
        {
+         sigproc_printf ("proc table overflow: hit %d processes, pid %d\n",
+                         nprocs, vchild->pid);
          rc = 0;
+         set_errno (EMFILE);   // FIXMENOW - what's the right errno?
          break;
        }
-      pchildren[nchildren] = vchild;
-      hchildren[nchildren] = vchild->hProcess;
-      if (!DuplicateHandle (hMainProc, vchild->hProcess, hMainProc, &vchild->pid_handle,
-                           0, 0, DUPLICATE_SAME_ACCESS))
-       system_printf ("Couldn't duplicate child handle for pid %d, %E", vchild->pid);
-      ProtectHandle1 (vchild->pid_handle, pid_handle);
-
-      if (!DuplicateHandle (hMainProc, hMainProc, vchild->hProcess, &vchild->ppid_handle,
-                           SYNCHRONIZE | PROCESS_DUP_HANDLE, TRUE, 0))
-       system_printf ("Couldn't duplicate my handle<%p> for pid %d, %E", hMainProc, vchild->pid);
+
       vchild->ppid = myself->pid;
       vchild->uid = myself->uid;
       vchild->gid = myself->gid;
       vchild->pgid = myself->pgid;
       vchild->sid = myself->sid;
       vchild->ctty = myself->ctty;
+      vchild->cygstarted = true;
       vchild->process_state |= PID_INITIALIZING | (myself->process_state & PID_USETTY);
-
-      sigproc_printf ("added pid %d to wait list, slot %d, winpid %p, handle %p",
-                 vchild->pid, nchildren, vchild->dwProcessId,
-                 vchild->hProcess);
-      nchildren++;
-
-      wake_wait_subproc ();
-      break;
-
-    /* A child process had terminated.
-       Possibly this is just due to an exec().  Cygwin implements an exec()
-       as a "handoff" from one windows process to another.  If child->hProcess
-       is different from what is recorded in hchildren, then this is an exec().
-       Otherwise this is a normal child termination event.
-       (called from wait_subproc thread) */
-    case PROC_CHILDTERMINATED:
-      if (hchildren[val] != pchildren[val]->hProcess)
-       {
-         sigproc_printf ("pid %d[%d], reparented old hProcess %p, new %p",
-                         pchildren[val]->pid, val, hchildren[val], pchildren[val]->hProcess);
-         HANDLE h = hchildren[val];
-         hchildren[val] = pchildren[val]->hProcess; /* Filled out by child */
-         ForceCloseHandle1 (h, childhProc);
-         ProtectHandle1 (pchildren[val]->hProcess, childhProc);
-         rc = 0;
-         goto out;                     // This was an exec()
-       }
-
-      sigproc_printf ("pid %d[%d] terminated, handle %p, nchildren %d, nzombies %d",
-                 pchildren[val]->pid, val, hchildren[val], nchildren, nzombies);
-
-      thiszombie = nzombies;
-      zombies[nzombies] = pchildren[val];      // Add to zombie array
-      zombies[nzombies++]->process_state = PID_ZOMBIE;// Walking dead
-
-      sigproc_printf ("zombifying [%d], pid %d, handle %p, nchildren %d",
-                     val, pchildren[val]->pid, hchildren[val], nchildren);
-      if ((int) val < --nchildren)
-       {
-         hchildren[val] = hchildren[nchildren];
-         pchildren[val] = pchildren[nchildren];
-       }
-
-      /* See if we should care about the this terminated process.  If we've
-        filled up our table or if we're ignoring SIGCHLD, then we immediately
-        remove the process and move on. Otherwise, this process becomes a zombie
-        which must be reaped by a wait() call.  FIXME:  This is a very inelegant
-        way to deal with this and could lead to process hangs.  */
-      if (nzombies >= NZOMBIES)
+      procs[nprocs] = vchild;
+      rc = procs[nprocs].wait ();
+      if (rc)
        {
-         sigproc_printf ("zombie table overflow %d", thiszombie);
-         remove_zombie (thiszombie);
+         sigproc_printf ("added pid %d to proc table, slot %d", vchild->pid,
+                         nprocs);
+         nprocs++;
        }
-
-      /* Don't scan the wait queue yet.  Caller will send SIGCHLD to this process.
-        This will cause an eventual scan of waiters. */
       break;
 
     /* Handle a wait4() operation.  Allocates an event for the calling
@@ -401,8 +303,8 @@ proc_subproc (DWORD what, DWORD val)
        */
       if ((wval->ev = wval->thread_ev) == NULL)
        {
-         wval->ev = wval->thread_ev = CreateEvent (&sec_none_nih, TRUE,
-                                                   FALSE, NULL);
+         wval->ev = wval->thread_ev = CreateEvent (&sec_none_nih, TRUE, FALSE,
+                                                   NULL);
          ProtectHandle1 (wval->ev, wq_ev);
        }
 
@@ -459,9 +361,8 @@ proc_subproc (DWORD what, DWORD val)
        }
 
       if (global_sigs[SIGCHLD].sa_handler == (void *) SIG_IGN)
-       while (nzombies)
-         remove_zombie (0);
-      break;
+       for (int i = 0; i < nprocs; i += remove_proc (i))
+         continue;
   }
 
 out:
@@ -492,54 +393,29 @@ _cygtls::remove_wq (DWORD wait)
  * Called on process exit.
  * Also called by spawn_guts to disassociate any subprocesses from this
  * process.  Subprocesses will then know to clean up after themselves and
- * will not become zombies.
+ * will not become procs.
  */
 void __stdcall
 proc_terminate (void)
 {
-  sigproc_printf ("nchildren %d, nzombies %d", nchildren, nzombies);
+  sigproc_printf ("nprocs %d", nprocs);
   /* Signal processing is assumed to be blocked in this routine. */
-  if (hwait_subproc)
+  if (nprocs)
     {
-      proc_loop_wait = 0;      // Tell wait_subproc thread to exit
       sync_proc_subproc->acquire (WPSP);
-      wake_wait_subproc ();    // Wake wait_subproc loop
-      hwait_subproc = NULL;
 
       (void) proc_subproc (PROC_CLEARWAIT, 1);
 
-      /* Clean out zombie processes from the pid list. */
+      /* Clean out proc processes from the pid list. */
       int i;
-      for (i = 0; i < nzombies; i++)
-       {
-         if (zombies[i]->hProcess)
-           {
-             ForceCloseHandle1 (zombies[i]->hProcess, childhProc);
-             ForceCloseHandle1 (zombies[i]->pid_handle, pid_handle);
-           }
-         zombies[i]->ppid = 1;
-         zombies[i]->process_state = PID_EXITED;       /* CGF FIXME - still needed? */
-         zombies[i].release ();        // FIXME: this breaks older gccs for some reason
-       }
-
-      /* Disassociate my subprocesses */
-      for (i = 0; i < nchildren; i++)
+      for (i = 0; i < nprocs; i++)
        {
-         if (!pchildren[i]->hProcess)
-           sigproc_printf ("%d(%d) hProcess cleared already?", pchildren[i]->pid,
-                       pchildren[i]->dwProcessId);
-         else
-           {
-             ForceCloseHandle1 (pchildren[i]->hProcess, childhProc);
-             sigproc_printf ("%d(%d) closed child handle", pchildren[i]->pid,
-                             pchildren[i]->dwProcessId);
-             pchildren[i]->ppid = 1;
-             if (pchildren[i]->pgid == myself->pid)
-               pchildren[i]->process_state |= PID_ORPHANED;
-           }
-         pchildren[i].release ();
+         procs[i]->ppid = 1;
+         if (!proc_exists (procs[i]))
+           procs[i]->process_state = PID_EXITED;       /* CGF FIXME - still needed? */
+         procs[i].release ();
        }
-      nchildren = nzombies = 0;
+      nprocs = 0;
       sync_proc_subproc->release ();
     }
   sigproc_printf ("leaving");
@@ -610,7 +486,7 @@ sigproc_init ()
   ProtectHandle (wait_sig_inited);
 
   /* sync_proc_subproc is used by proc_subproc.  It serialises
-   * access to the children and zombie arrays.
+   * access to the children and proc arrays.
    */
   new_muto (sync_proc_subproc);
 
@@ -648,7 +524,7 @@ sigproc_terminate (void)
          CloseHandle (sendsig);
        }
     }
-  proc_terminate ();           // Terminate process handling thread
+  proc_terminate ();           // clean up process stuff
 
   return;
 }
@@ -833,25 +709,6 @@ out:
   return rc;
 }
 
-/* Initialize the wait_subproc thread.
- * Called from fork() or spawn() to initialize the handling of subprocesses.
- */
-void __stdcall
-subproc_init (void)
-{
-  if (hwait_subproc)
-    return;
-
-  /* A "wakeup" handle which can be toggled to make wait_subproc reexamine
-   * the hchildren array.
-   */
-  events[0] = CreateEvent (&sec_none_nih, FALSE, FALSE, NULL);
-  hwait_subproc = new cygthread (wait_subproc, NULL, "proc");
-  hwait_subproc->zap_h ();
-  ProtectHandle (events[0]);
-  sigproc_printf ("started wait_subproc thread");
-}
-
 /* Initialize some of the memory block passed to child processes
    by fork/spawn/exec. */
 
@@ -864,7 +721,6 @@ init_child_info (DWORD chtype, child_info *ch, HANDLE subproc_ready)
   ch->magic = CHILD_INFO_MAGIC;
   ch->type = chtype;
   ch->subproc_ready = subproc_ready;
-  ch->pppid_handle = myself->ppid_handle;
   ch->fhandler_union_cb = sizeof (fhandler_union);
   ch->user_h = cygwin_user_h;
 }
@@ -877,132 +733,107 @@ checkstate (waitq *parent_w)
 {
   int potential_match = 0;
 
-  sigproc_printf ("nchildren %d, nzombies %d", nchildren, nzombies);
+  sigproc_printf ("nprocs %d", nprocs);
 
   /* Check already dead processes first to see if they match the criteria
-   * given in w->next.
-   */
-  for (int i = 0; i < nzombies; i++)
-    switch (stopped_or_terminated (parent_w, zombies[i]))
+   * given in w->next.  */
+  int res;
+  for (int i = 0; i < nprocs; i++)
+    if ((res = stopped_or_terminated (parent_w, procs[i])))
       {
-      case -1:
-       potential_match = -1;
-       break;
-      case 1:
-       remove_zombie (i);
+       remove_proc (i);
        potential_match = 1;
        goto out;
       }
 
-  sigproc_printf ("checking alive children");
-
-  /* No dead terminated children matched.  Check for stopped children. */
-  for (int i = 0; i < nchildren; i++)
-    switch (stopped_or_terminated (parent_w, pchildren[i]))
-      {
-      case -1:
-       potential_match = -1;
-       break;
-      case 1:
-       potential_match = 1;
-       goto out;
-      }
+  sigproc_printf ("no matching terminated children found");
+  potential_match = -!!nprocs;
 
 out:
   sigproc_printf ("returning %d", potential_match);
   return potential_match;
 }
 
-/* Remove a zombie from zombies by swapping it with the last child in the list.
- */
-static void __stdcall
-remove_zombie (int ci)
+/* Remove a proc from procs by swapping it with the last child in the list.
  Also releases shared memory of exited processes.  */
+static bool __stdcall
+remove_proc (int ci)
 {
-  sigproc_printf ("removing %d, pid %d, nzombies %d", ci, zombies[ci]->pid,
-                 nzombies);
+  if (proc_exists (procs[ci]))
+    return true;
 
-  if (zombies[ci])
+  sigproc_printf ("removing procs[%d], pid %d, nprocs %d", ci, procs[ci]->pid,
+                 nprocs);
+  if (procs[ci] != myself)
     {
-      ForceCloseHandle1 (zombies[ci]->hProcess, childhProc);
-      ForceCloseHandle1 (zombies[ci]->pid_handle, pid_handle);
-      zombies[ci].release ();
+      procs[ci].release ();
+      if (procs[ci].pid_handle)
+       ForceCloseHandle1 (procs[ci].pid_handle, childhProc);
+      if (procs[ci].hProcess)
+       ForceCloseHandle1 (procs[ci].hProcess, childhProc);
     }
-
-  if (ci < --nzombies)
-    zombies[ci] = zombies[nzombies];
-
-  return;
+  if (ci < --nprocs)
+    procs[ci] = procs[nprocs];
+  return 0;
 }
 
 /* Check status of child process vs. waitq member.
- *
- * parent_w is the pointer to the parent of the waitq member in question.
- * child is the subprocess being considered.
- *
- * Returns
- *   1 if stopped or terminated child matches parent_w->next criteria
- *  -1 if a non-stopped/terminated child matches parent_w->next criteria
- *   0 if child does not match parent_w->next criteria
- */
-static int __stdcall
+  
+   parent_w is the pointer to the parent of the waitq member in question.
+   child is the subprocess being considered.
+  
+   Returns non-zero if waiting thread released.  */
+static bool __stdcall
 stopped_or_terminated (waitq *parent_w, _pinfo *child)
 {
-  int potential_match;
+  int might_match;
   waitq *w = parent_w->next;
 
   sigproc_printf ("considering pid %d", child->pid);
   if (w->pid == -1)
-    potential_match = 1;
+    might_match = 1;
   else if (w->pid == 0)
-    potential_match = child->pgid == myself->pgid;
+    might_match = child->pgid == myself->pgid;
   else if (w->pid < 0)
-    potential_match = child->pgid == -w->pid;
+    might_match = child->pgid == -w->pid;
   else
-    potential_match = (w->pid == child->pid);
+    might_match = (w->pid == child->pid);
 
-  if (!potential_match)
+  if (!might_match)
     return 0;
 
-  bool terminated;
+  int terminated;
 
-  if ((terminated = child->process_state == PID_ZOMBIE) ||
-      ((w->options & WUNTRACED) && child->stopsig))
-    {
-      parent_w->next = w->next;        /* successful wait.  remove from wait queue */
-      w->pid = child->pid;
+  if (!((terminated = (child->process_state == PID_ZOMBIE)) ||
+      ((w->options & WUNTRACED) && child->stopsig)))
+    return 0;
 
-      if (!terminated)
-       {
-         sigproc_printf ("stopped child");
-         w->status = (child->stopsig << 8) | 0x7f;
-         child->stopsig = 0;
-       }
-      else /* Should only get here when child has been moved to the zombies array */
-       {
-         DWORD status;
-         if (!GetExitCodeProcess (child->hProcess, &status))
-           status = 0xffff;
-         if (status & EXIT_SIGNAL)
-           w->status = (status >> 8) & 0xff;   /* exited due to signal */
-         else
-           w->status = (status & 0xff) << 8;   /* exited via "exit ()" */
+  parent_w->next = w->next;    /* successful wait.  remove from wait queue */
+  w->pid = child->pid;
 
-         add_rusage (&myself->rusage_children, &child->rusage_children);
-         add_rusage (&myself->rusage_children, &child->rusage_self);
+  if (!terminated)
+    {
+      sigproc_printf ("stopped child");
+      w->status = (child->stopsig << 8) | 0x7f;
+      child->stopsig = 0;
+    }
+  else /* Should only get here when child has been moved to the procs array */
+    {
+      w->status = child->exitcode;
 
-         if (w->rusage)
-           {
-             add_rusage ((struct rusage *) w->rusage, &child->rusage_children);
-             add_rusage ((struct rusage *) w->rusage, &child->rusage_self);
-           }
-       }
+      add_rusage (&myself->rusage_children, &child->rusage_children);
+      add_rusage (&myself->rusage_children, &child->rusage_self);
 
-      if (!SetEvent (w->ev))   /* wake up wait4 () immediately */
-       system_printf ("couldn't wake up wait event %p, %E", w->ev);
-      return 1;
+      if (w->rusage)
+       {
+         add_rusage ((struct rusage *) w->rusage, &child->rusage_children);
+         add_rusage ((struct rusage *) w->rusage, &child->rusage_self);
+       }
     }
 
-  return -potential_match;
+  if (!SetEvent (w->ev))       /* wake up wait4 () immediately */
+    system_printf ("couldn't wake up wait event %p, %E", w->ev);
+  return true;
 }
 
 static void
@@ -1078,27 +909,10 @@ wait_sig (VOID *self)
      signals.  Prior to this, dwProcessId was set to the windows pid of
      of the original windows process which spawned us unless this was a
      "toplevel" process.  */
-  myself->dwProcessId = GetCurrentProcessId ();
   myself->process_state |= PID_ACTIVE;
   myself->process_state &= ~PID_INITIALIZING;
 
   sigproc_printf ("myself->dwProcessId %u", myself->dwProcessId);
-  /* If we've been execed, then there is still a stub left in the previous
-     windows process waiting to see if it's started a cygwin process or not.
-     Signalling subproc_ready indicates that we are a cygwin process.  */
-  if (child_proc_info && child_proc_info->type == PROC_EXEC)
-    {
-      debug_printf ("subproc_ready %p", child_proc_info->subproc_ready);
-      if (!SetEvent (child_proc_info->subproc_ready))
-       system_printf ("SetEvent (subproc_ready) failed, %E");
-      ForceCloseHandle1 (child_proc_info->subproc_ready, subproc_ready);
-      /* Initialize an "indirect" pid block so that if someone looks up this
-        process via its Windows PID it will be redirected to the appropriate
-        Cygwin PID shared memory block. */
-      static pinfo NO_COPY myself_identity;
-      myself_identity.init (cygwin_pid (myself->dwProcessId), PID_EXECED);
-    }
-
   SetEvent (wait_sig_inited);
   sigtid = GetCurrentThreadId ();
 
@@ -1215,85 +1029,3 @@ wait_sig (VOID *self)
   sigproc_printf ("done");
   ExitThread (0);
 }
-
-/* Wait for subprocesses to terminate. Executes in a separate thread. */
-static DWORD WINAPI
-wait_subproc (VOID *)
-{
-  sigproc_printf ("starting");
-  int errloop = 0;
-
-  for (;;)
-    {
-      DWORD rc = WaitForMultipleObjects (nchildren + 1, events, FALSE,
-                                        proc_loop_wait);
-      if (!proc_loop_wait)
-       break;
-      if (rc == WAIT_TIMEOUT)
-       continue;
-
-      if (rc == WAIT_FAILED)
-       {
-         /* It's ok to get an ERROR_INVALID_HANDLE since another thread may have
-            closed a handle in the children[] array.  So, we try looping a couple
-            of times to stabilize. FIXME - this is not foolproof.  Probably, this
-            thread should be responsible for closing the children. */
-         if (!errloop++)
-           proc_subproc (PROC_NOTHING, 0);     // Just synchronize and continue
-         if (errloop < 10)
-           continue;
-
-         system_printf ("wait failed. nchildren %d, wait %d, %E",
-                       nchildren, proc_loop_wait);
-
-         for (int i = 0; i <= nchildren; i++)
-           if ((rc = WaitForSingleObject (events[i], 0)) == WAIT_OBJECT_0 ||
-               rc == WAIT_TIMEOUT)
-             continue;
-           else if (i == 0)
-               system_printf ("nchildren %d, event[%d] %p, %E", nchildren, i, events[i]);
-           else
-             {
-               system_printf ("nchildren %d, event[%d] %p, pchildren[%d] %p, events[0] %p, %E",
-                              nchildren, i, events[i], i - 1, (_pinfo *) pchildren[i - 1], events[0]);
-               system_printf ("pid %d, dwProcessId %u, hProcess %p, progname '%s'",
-                              pchildren[i - 1]->pid, pchildren[i - 1]->dwProcessId,
-                              pchildren[i - 1]->hProcess, pchildren[i - 1]->progname);
-             }
-         break;
-       }
-
-      errloop = 0;
-      rc -= WAIT_OBJECT_0;
-      if (rc-- != 0)
-       {
-         siginfo_t si;
-         si.si_signo = SIGCHLD;
-         si.si_code = SI_KERNEL;
-         si.si_pid = pchildren[rc]->pid;
-         si.si_uid = pchildren[rc]->uid;
-         si.si_errno = 0;
-         GetExitCodeProcess (hchildren[rc], (DWORD *) &si.si_status);
-#if 0  // FIXME: This is tricky to get right
-         si.si_utime = pchildren[rc]->rusage_self.ru_utime;
-         si.si_stime = pchildren[rc].rusage_self.ru_stime;
-#else
-         si.si_utime = 0;
-         si.si_stime = 0;
-#endif
-         rc = proc_subproc (PROC_CHILDTERMINATED, rc);
-
-         /* Send a SIGCHLD to myself.   We do this here, rather than in proc_subproc
-            to avoid the proc_subproc lock since the signal thread will eventually
-            be calling proc_subproc and could unnecessarily block. */
-         if (rc)
-           sig_send (myself_nowait, si);
-       }
-      sigproc_printf ("looping");
-    }
-
-  ForceCloseHandle (events[0]);
-  events[0] = NULL;
-  sigproc_printf ("done");
-  ExitThread (0);
-}
index 776d1d9..9c7807a 100644 (file)
@@ -12,10 +12,6 @@ details. */
 #define _SIGPROC_H
 #include <signal.h>
 
-#define EXIT_SIGNAL     0x010000
-#define EXIT_REPARENTING 0x020000
-#define EXIT_NOCLOSEALL  0x040000
-
 #ifdef NSIG
 enum
 {
@@ -26,7 +22,8 @@ enum
   __SIGDELETE      = -(NSIG + 5),
   __SIGFLUSHFAST    = -(NSIG + 6),
   __SIGHOLD        = -(NSIG + 7),
-  __SIGNOHOLD      = -(NSIG + 8)
+  __SIGNOHOLD      = -(NSIG + 8),
+  __SIGREPARENT            = (NSIG + 2)
 };
 #endif
 
@@ -77,7 +74,6 @@ int __stdcall proc_subproc (DWORD, DWORD) __attribute__ ((regparm (2)));
 class _pinfo;
 void __stdcall proc_terminate ();
 void __stdcall sigproc_init ();
-void __stdcall subproc_init ();
 void __stdcall sigproc_terminate ();
 bool __stdcall proc_exists (_pinfo *) __attribute__ ((regparm(1)));
 bool __stdcall pid_exists (pid_t) __attribute__ ((regparm(1)));
index db4210b..426ee11 100644 (file)
@@ -29,8 +29,6 @@ details. */
 #include "child_info.h"
 #include "shared_info.h"
 #include "pinfo.h"
-#define NEED_VFORK
-#include "perthread.h"
 #include "registry.h"
 #include "environ.h"
 #include "cygthread.h"
@@ -384,16 +382,7 @@ spawn_guts (const char * prog_arg, const char *const *argv,
   else
     chtype = PROC_EXEC;
 
-  HANDLE subproc_ready;
-  if (chtype != PROC_EXEC)
-    subproc_ready = NULL;
-  else
-    {
-      subproc_ready = CreateEvent (&sec_all, TRUE, FALSE, NULL);
-      ProtectHandleINH (subproc_ready);
-    }
-
-  init_child_info (chtype, &ciresrv, subproc_ready);
+  init_child_info (chtype, &ciresrv, NULL);
 
   ciresrv.moreinfo = (cygheap_exec_info *) ccalloc (HEAP_1_EXEC, 1, sizeof (cygheap_exec_info));
   ciresrv.moreinfo->old_title = NULL;
@@ -603,7 +592,6 @@ spawn_guts (const char * prog_arg, const char *const *argv,
 
   ciresrv.moreinfo->argc = newargv.argc;
   ciresrv.moreinfo->argv = newargv;
-  ciresrv.hexec_proc = hexec_proc;
 
   if (mode != _P_OVERLAY ||
       !DuplicateHandle (hMainProc, myself.shared_handle (), hMainProc,
@@ -627,19 +615,35 @@ spawn_guts (const char * prog_arg, const char *const *argv,
 
   if (mode == _P_DETACH || !set_console_state_for_spawn ())
     flags |= DETACHED_PROCESS;
+
+  HANDLE saved_sendsig;
   if (mode != _P_OVERLAY)
-    flags |= CREATE_SUSPENDED;
-#if 0 //someday
+    saved_sendsig = NULL;
   else
-    myself->dwProcessId = 0;
-#endif
+    {
+      /* Reset sendsig so that any process which wants to send a signal
+        to this pid will wait for the new process to become active.
+        Save the old value in case the exec fails.  */
+      saved_sendsig = myself->sendsig;
+      myself->sendsig = INVALID_HANDLE_VALUE;
+      /* Save a copy of a handle to the current process around the first time we
+        exec so that the pid will not be reused.  Why did I stop cygwin from
+        generating its own pids again? */
+      if (cygheap->pid_handle)
+       /* already done previously */;
+      else if (DuplicateHandle (hMainProc, hMainProc, hMainProc, &cygheap->pid_handle,
+                               PROCESS_QUERY_INFORMATION, TRUE, 0))
+       ProtectHandle (cygheap->pid_handle);
+      else
+       system_printf ("duplicate to pid_handle failed, %E");
+    }
 
-  /* Some file types (currently only sockets) need extra effort in the
-     parent after CreateProcess and before copying the datastructures
-     to the child. So we have to start the child in suspend state,
-     unfortunately, to avoid a race condition. */
-  if (cygheap->fdtab.need_fixup_before ())
-    flags |= CREATE_SUSPENDED;
+  /* Start the process in a suspended state.  Needed so that any potential parent will
+     be able to take notice of the new "execed" process.  This is only really needed
+     to handle exec'ed windows processes since cygwin processes are smart enough that
+     the parent doesn't have to bother but what are you gonna do?  Cygwin lives in
+     a windows world. */
+  flags |= CREATE_SUSPENDED;
 
   const char *runpath = null_app_name ? NULL : (const char *) real_path;
 
@@ -718,7 +722,7 @@ spawn_guts (const char * prog_arg, const char *const *argv,
   /* Restore impersonation. In case of _P_OVERLAY this isn't
      allowed since it would overwrite child data. */
   if (mode != _P_OVERLAY || !rc)
-      cygheap->user.reimpersonate ();
+    cygheap->user.reimpersonate ();
 
   MALLOC_CHECK;
   if (envblock)
@@ -732,12 +736,9 @@ spawn_guts (const char * prog_arg, const char *const *argv,
     {
       __seterrno ();
       syscall_printf ("CreateProcess failed, %E");
-#if 0 // someday
-      if (mode == _P_OVERLAY)
-       myself->dwProcessId = GetCurrentProcessId ();
-#endif
-      if (subproc_ready)
-       ForceCloseHandle (subproc_ready);
+      /* If this was a failed exec, restore the saved sendsig. */
+      if (saved_sendsig)
+       myself->sendsig = saved_sendsig;
       cygheap_setup_for_child_cleanup (newheap, &ciresrv, 0);
       return -1;
     }
@@ -765,11 +766,6 @@ spawn_guts (const char * prog_arg, const char *const *argv,
     {
       cygheap->fdtab.fixup_before_exec (pi.dwProcessId);
       cygheap_setup_for_child_cleanup (newheap, &ciresrv, 1);
-      if (mode == _P_OVERLAY)
-       {
-         ResumeThread (pi.hThread);
-         cygthread::terminate ();
-       }
     }
 
   if (mode != _P_OVERLAY)
@@ -784,18 +780,36 @@ spawn_guts (const char * prog_arg, const char *const *argv,
   /* Name the handle similarly to proc_subproc. */
   ProtectHandle1 (pi.hProcess, childhProc);
 
+  int wait_for_myself = false;
+  DWORD exec_cygstarted;
   if (mode == _P_OVERLAY)
     {
-      /* These are both duplicated in the child code.  We do this here,
-        primarily for strace. */
+      /* Store the old exec_cygstarted since this is used as a crude semaphore for
+        detecting when the parent has noticed the change in windows pid for this
+        cygwin pid. */
+      exec_cygstarted = myself->cygstarted;
+      myself->dwProcessId = dwExeced = pi.dwProcessId;  /* Reparenting needs this */
+      myself.alert_parent (__SIGREPARENT);
+      CloseHandle (saved_sendsig);
       strace.execing = 1;
       hExeced = pi.hProcess;
-      dwExeced = pi.dwProcessId;
       strcpy (myself->progname, real_path);
       close_all_files ();
+      /* If wr_proc_pipe doesn't exist then this process was not started by a cygwin
+        process.  So, we need to wait around until the process we've just "execed"
+        dies.  Use our own wait facility to wait for our own pid to exit (there
+        is some minor special case code in proc_waiter and friends to accommodeate
+        this). */
+      if (!myself->wr_proc_pipe)
+       {
+         myself.hProcess = pi.hProcess;
+         myself.remember ();
+         wait_for_myself = true;
+       }
     }
   else
     {
+      exec_cygstarted = 0;
       myself->set_has_pgid_children ();
       ProtectHandle (pi.hThread);
       pinfo child (cygpid, PID_IN_USE);
@@ -808,7 +822,7 @@ spawn_guts (const char * prog_arg, const char *const *argv,
          goto out;
        }
       child->dwProcessId = pi.dwProcessId;
-      child->hProcess = pi.hProcess;
+      child.hProcess = pi.hProcess;
       if (!child.remember ())
        {
          syscall_printf ("process table full");
@@ -825,101 +839,31 @@ spawn_guts (const char * prog_arg, const char *const *argv,
         However, we should try to find another way to do this eventually. */
       (void) DuplicateHandle (hMainProc, child.shared_handle (), pi.hProcess,
                              NULL, 0, 0, DUPLICATE_SAME_ACCESS);
-      /* Start the child running */
-      ResumeThread (pi.hThread);
     }
 
+  /* Start the child running */
+  if (flags & CREATE_SUSPENDED)
+    ResumeThread (pi.hThread);
   ForceCloseHandle (pi.hThread);
+  // ForceCloseHandle (pi.hProcess);  // handled by proc_subproc and friends
 
   sigproc_printf ("spawned windows pid %d", pi.dwProcessId);
 
-  bool exited;
-
-  res = 0;
-  exited = false;
-  MALLOC_CHECK;
-  if (mode == _P_OVERLAY)
+  if (wait_for_myself)
+    waitpid (myself->pid, &res, 0);
+  else
     {
-      int nwait = 3;
-      HANDLE waitbuf[3] = {pi.hProcess, signal_arrived, subproc_ready};
-      for (int i = 0; i < 100; i++)
-       {
-         switch (WaitForMultipleObjects (nwait, waitbuf, FALSE, INFINITE))
-           {
-           case WAIT_OBJECT_0:
-             sigproc_printf ("subprocess exited");
-             DWORD exitcode;
-             if (!GetExitCodeProcess (pi.hProcess, &exitcode))
-               exitcode = 1;
-             res |= exitcode;
-             exited = true;
-             break;
-           case WAIT_OBJECT_0 + 1:
-             sigproc_printf ("signal arrived");
-             reset_signal_arrived ();
-             continue;
-           case WAIT_OBJECT_0 + 2:
-             if (my_parent_is_alive ())
-               res |= EXIT_REPARENTING;
-             else if (!myself->ppid_handle)
-               {
-                 nwait = 2;
-                 sigproc_terminate ();
-                 continue;
-               }
-             break;
-           case WAIT_FAILED:
-             system_printf ("wait failed: nwait %d, pid %d, winpid %d, %E",
-                            nwait, myself->pid, myself->dwProcessId);
-             system_printf ("waitbuf[0] %p %d", waitbuf[0],
-                            WaitForSingleObject (waitbuf[0], 0));
-             system_printf ("waitbuf[1] %p %d", waitbuf[1],
-                            WaitForSingleObject (waitbuf[1], 0));
-             system_printf ("waitbuf[w] %p %d", waitbuf[2],
-                            WaitForSingleObject (waitbuf[2], 0));
-             set_errno (ECHILD);
-             try_to_debug ();
-             return -1;
-           }
-         break;
-       }
-
-      ForceCloseHandle (subproc_ready);
-
-      sigproc_printf ("res %p", res);
-
-      if (res & EXIT_REPARENTING)
-       {
-         /* Try to reparent child process.
-          * Make handles to child available to parent process and exit with
-          * EXIT_REPARENTING status. Wait() syscall in parent will then wait
-          * for newly created child.
-          */
-         HANDLE oldh = myself->hProcess;
-         HANDLE h = myself->ppid_handle;
-         sigproc_printf ("parent handle %p", h);
-         int rc = DuplicateHandle (hMainProc, pi.hProcess, h, &myself->hProcess,
-                                   0, FALSE, DUPLICATE_SAME_ACCESS);
-         sigproc_printf ("%d = DuplicateHandle, oldh %p, newh %p",
-                         rc, oldh, myself->hProcess);
-         VerifyHandle (myself->hProcess);
-         if (!rc && my_parent_is_alive ())
-           {
-             system_printf ("Reparent failed, parent handle %p, %E", h);
-             system_printf ("my dwProcessId %d, myself->dwProcessId %d",
-                            GetCurrentProcessId (), myself->dwProcessId);
-             system_printf ("old hProcess %p, hProcess %p", oldh, myself->hProcess);
-           }
-       }
-
+      /* Loop, waiting for parent to notice pid change, if exec_cygstarted.
+         In theory this wait should be a no-op.  */
+      if (exec_cygstarted)
+       while (myself->cygstarted == exec_cygstarted)
+         low_priority_sleep (0);
+      res = 42;
     }
 
-  MALLOC_CHECK;
-
   switch (mode)
     {
     case _P_OVERLAY:
-      ForceCloseHandle1 (pi.hProcess, childhProc);
       myself->exit (res, 1);
       break;
     case _P_WAIT:
@@ -986,7 +930,6 @@ spawnve (int mode, const char *path, const char *const *argv,
     case _P_WAIT:
     case _P_DETACH:
     case _P_SYSTEM:
-      subproc_init ();
       ret = spawn_guts (path, argv, envp, mode);
 #ifdef NEWVFORK
       if (vf)
index fded062..262dcdd 100644 (file)
@@ -56,8 +56,6 @@ details. */
 #include "pinfo.h"
 #include "shared_info.h"
 #include "cygheap.h"
-#define NEED_VFORK
-#include "perthread.h"
 #include "pwdgrp.h"
 #include "cpuid.h"
 #include "registry.h"
index 8e836e9..e7ce45a 100644 (file)
@@ -16,7 +16,6 @@ details. */
 #include "hires.h"
 #include "thread.h"
 #include "cygtls.h"
-#include "cygthread.h"
 #include "sigproc.h"
 #include "sync.h"
 
index 12eb821..a6fac1a 100644 (file)
@@ -23,7 +23,6 @@ details. */
 #include "pinfo.h"
 #include "hires.h"
 #include "cygtls.h"
-#include "cygthread.h"
 #include "sigproc.h"
 #include "sync.h"
 
index e6b955c..a99b38b 100644 (file)
 //;# autogenerated:  Do not edit.
 
-//; $tls::sizeof__cygtls = 3932;
-//; $tls::func = -3932;
+//; $tls::sizeof__cygtls = 3936;
+//; $tls::func = -3936;
 //; $tls::pfunc = 0;
-//; $tls::saved_errno = -3928;
+//; $tls::saved_errno = -3932;
 //; $tls::psaved_errno = 4;
-//; $tls::sa_flags = -3924;
+//; $tls::sa_flags = -3928;
 //; $tls::psa_flags = 8;
-//; $tls::oldmask = -3920;
+//; $tls::oldmask = -3924;
 //; $tls::poldmask = 12;
-//; $tls::deltamask = -3916;
+//; $tls::deltamask = -3920;
 //; $tls::pdeltamask = 16;
-//; $tls::event = -3912;
+//; $tls::event = -3916;
 //; $tls::pevent = 20;
-//; $tls::errno_addr = -3908;
+//; $tls::errno_addr = -3912;
 //; $tls::perrno_addr = 24;
-//; $tls::initialized = -3904;
+//; $tls::initialized = -3908;
 //; $tls::pinitialized = 28;
-//; $tls::sigmask = -3900;
+//; $tls::sigmask = -3904;
 //; $tls::psigmask = 32;
-//; $tls::sigwait_mask = -3896;
+//; $tls::sigwait_mask = -3900;
 //; $tls::psigwait_mask = 36;
-//; $tls::sigwait_info = -3892;
+//; $tls::sigwait_info = -3896;
 //; $tls::psigwait_info = 40;
-//; $tls::threadkill = -3888;
+//; $tls::threadkill = -3892;
 //; $tls::pthreadkill = 44;
-//; $tls::infodata = -3884;
+//; $tls::infodata = -3888;
 //; $tls::pinfodata = 48;
-//; $tls::tid = -3736;
+//; $tls::tid = -3740;
 //; $tls::ptid = 196;
-//; $tls::local_clib = -3732;
+//; $tls::local_clib = -3736;
 //; $tls::plocal_clib = 200;
-//; $tls::__dontuse = -3732;
+//; $tls::__dontuse = -3736;
 //; $tls::p__dontuse = 200;
-//; $tls::locals = -2668;
+//; $tls::locals = -2672;
 //; $tls::plocals = 1264;
+//; $tls::_ctinfo = -1084;
+//; $tls::p_ctinfo = 2852;
 //; $tls::wq = -1080;
-//; $tls::pwq = 2852;
+//; $tls::pwq = 2856;
 //; $tls::prev = -1052;
-//; $tls::pprev = 2880;
+//; $tls::pprev = 2884;
 //; $tls::next = -1048;
-//; $tls::pnext = 2884;
+//; $tls::pnext = 2888;
 //; $tls::stackptr = -1044;
-//; $tls::pstackptr = 2888;
+//; $tls::pstackptr = 2892;
 //; $tls::sig = -1040;
-//; $tls::psig = 2892;
+//; $tls::psig = 2896;
 //; $tls::incyg = -1036;
-//; $tls::pincyg = 2896;
+//; $tls::pincyg = 2900;
 //; $tls::spinning = -1032;
-//; $tls::pspinning = 2900;
+//; $tls::pspinning = 2904;
 //; $tls::stacklock = -1028;
-//; $tls::pstacklock = 2904;
+//; $tls::pstacklock = 2908;
 //; $tls::stack = -1024;
-//; $tls::pstack = 2908;
+//; $tls::pstack = 2912;
 //; $tls::padding = 0;
-//; $tls::ppadding = 3932;
+//; $tls::ppadding = 3936;
 //; __DATA__
 
-#define tls_func (-3932)
+#define tls_func (-3936)
 #define tls_pfunc (0)
-#define tls_saved_errno (-3928)
+#define tls_saved_errno (-3932)
 #define tls_psaved_errno (4)
-#define tls_sa_flags (-3924)
+#define tls_sa_flags (-3928)
 #define tls_psa_flags (8)
-#define tls_oldmask (-3920)
+#define tls_oldmask (-3924)
 #define tls_poldmask (12)
-#define tls_deltamask (-3916)
+#define tls_deltamask (-3920)
 #define tls_pdeltamask (16)
-#define tls_event (-3912)
+#define tls_event (-3916)
 #define tls_pevent (20)
-#define tls_errno_addr (-3908)
+#define tls_errno_addr (-3912)
 #define tls_perrno_addr (24)
-#define tls_initialized (-3904)
+#define tls_initialized (-3908)
 #define tls_pinitialized (28)
-#define tls_sigmask (-3900)
+#define tls_sigmask (-3904)
 #define tls_psigmask (32)
-#define tls_sigwait_mask (-3896)
+#define tls_sigwait_mask (-3900)
 #define tls_psigwait_mask (36)
-#define tls_sigwait_info (-3892)
+#define tls_sigwait_info (-3896)
 #define tls_psigwait_info (40)
-#define tls_threadkill (-3888)
+#define tls_threadkill (-3892)
 #define tls_pthreadkill (44)
-#define tls_infodata (-3884)
+#define tls_infodata (-3888)
 #define tls_pinfodata (48)
-#define tls_tid (-3736)
+#define tls_tid (-3740)
 #define tls_ptid (196)
-#define tls_local_clib (-3732)
+#define tls_local_clib (-3736)
 #define tls_plocal_clib (200)
-#define tls___dontuse (-3732)
+#define tls___dontuse (-3736)
 #define tls_p__dontuse (200)
-#define tls_locals (-2668)
+#define tls_locals (-2672)
 #define tls_plocals (1264)
+#define tls__ctinfo (-1084)
+#define tls_p_ctinfo (2852)
 #define tls_wq (-1080)
-#define tls_pwq (2852)
+#define tls_pwq (2856)
 #define tls_prev (-1052)
-#define tls_pprev (2880)
+#define tls_pprev (2884)
 #define tls_next (-1048)
-#define tls_pnext (2884)
+#define tls_pnext (2888)
 #define tls_stackptr (-1044)
-#define tls_pstackptr (2888)
+#define tls_pstackptr (2892)
 #define tls_sig (-1040)
-#define tls_psig (2892)
+#define tls_psig (2896)
 #define tls_incyg (-1036)
-#define tls_pincyg (2896)
+#define tls_pincyg (2900)
 #define tls_spinning (-1032)
-#define tls_pspinning (2900)
+#define tls_pspinning (2904)
 #define tls_stacklock (-1028)
-#define tls_pstacklock (2904)
+#define tls_pstacklock (2908)
 #define tls_stack (-1024)
-#define tls_pstack (2908)
+#define tls_pstack (2912)
 #define tls_padding (0)
-#define tls_ppadding (3932)
+#define tls_ppadding (3936)
index edad95c..ef77bd5 100644 (file)
@@ -57,7 +57,7 @@ ttyslot (void)
 void __stdcall
 tty_init (void)
 {
-  if (!myself->ppid_handle && NOTSTATE (myself, PID_CYGPARENT))
+  if (!myself->cygstarted && NOTSTATE (myself, PID_CYGPARENT))
     cygheap->fdtab.get_debugger_info ();
 
   if (NOTSTATE (myself, PID_USETTY))
index 7d1f13a..70febf0 100644 (file)
@@ -13,7 +13,6 @@ details. */
 #include <stdlib.h>
 #include "cygerrno.h"
 #include "sigproc.h"
-#include "perthread.h"
 #include "thread.h"
 #include "cygtls.h"
 
index a04f7c5..2c5fcce 100644 (file)
@@ -23,7 +23,6 @@ details. */
 #include "cygerrno.h"
 #include "perprocess.h"
 #include "security.h"
-#include "cygthread.h"
 #include "thread.h"
 #include "cygtls.h"
 #include "sync.h"