OSDN Git Service

* pinfo.h (_pinfo::set_exit_state): Declare new function.
authorcgf <cgf>
Tue, 11 Jan 2005 15:31:01 +0000 (15:31 +0000)
committercgf <cgf>
Tue, 11 Jan 2005 15:31:01 +0000 (15:31 +0000)
(pinfo::exit): Move here from _pinfo::exit.
* sigproc.cc (child_info::sync): Use new function to set exitcode and
process_state.
* pinfo.cc (_pinfo::exit): Ditto.
(proc_waiter): Ditto.
(_pinfo::set_exit_state): Define new function.
(_pinfo::dup_proc_pipe): Close handle when there is no parent process around to
care about the exit value.
* dcrt0.cc (dll_crt0_0): Move subproc_ready synchronization later to make sure
that myself is still mapped in parent.
(do_exit): Reflect movement to pinfo::exit.
(__api_fatal): Ditto.
* exceptions.cc (signal_exit): Ditto.
* errno.cc (errmap): Map PROC_NOT_FOUND.
* init.cc (dll_entry): Release myself before exiting.
* sigproc.cc (proc_can_be_signalled): Set errno appropriately.
(sig_send): Ditto.  Also remove ill-advised test for !myself->sendsig since
this is an indication of a process which is still initializating -- it is not
an error.
(child_info::sync): Don't set exitcode here.  Assume that will happen in
proc_waiter, if necessary.
* spawn.cc (spawn_guts): Delay "wait_for_myself" logic until later.  Don't wait
at all if the process has already exited.  Reflect movement to pinfo::exit.

winsup/cygwin/ChangeLog
winsup/cygwin/dcrt0.cc
winsup/cygwin/errno.cc
winsup/cygwin/exceptions.cc
winsup/cygwin/init.cc
winsup/cygwin/pinfo.cc
winsup/cygwin/pinfo.h
winsup/cygwin/sigproc.cc
winsup/cygwin/spawn.cc
winsup/cygwin/strace.cc

index b07de4a..23dc35e 100644 (file)
@@ -1,3 +1,31 @@
+2005-01-11  Christopher Faylor  <cgf@timesys.com>
+
+       * pinfo.h (_pinfo::set_exit_state): Declare new function.
+       (pinfo::exit): Move here from _pinfo::exit.
+       * sigproc.cc (child_info::sync): Use new function to set exitcode and
+       process_state.
+       * pinfo.cc (_pinfo::exit): Ditto.
+       (proc_waiter): Ditto.
+       (_pinfo::set_exit_state): Define new function.
+       (_pinfo::dup_proc_pipe): Close handle when there is no parent process
+       around to care about the exit value.
+       * dcrt0.cc (dll_crt0_0): Move subproc_ready synchronization later to
+       make sure that myself is still mapped in parent.
+       (do_exit): Reflect movement to pinfo::exit.
+       (__api_fatal): Ditto.
+       * exceptions.cc (signal_exit): Ditto.
+       * errno.cc (errmap): Map PROC_NOT_FOUND.
+       * init.cc (dll_entry): Release myself before exiting.
+       * sigproc.cc (proc_can_be_signalled): Set errno appropriately.
+       (sig_send): Ditto.  Also remove ill-advised test for !myself->sendsig
+       since this is an indication of a process which is still initializating
+       -- it is not an error.
+       (child_info::sync): Don't set exitcode here.  Assume that will happen
+       in proc_waiter, if necessary.
+       * spawn.cc (spawn_guts): Delay "wait_for_myself" logic until later.
+       Don't wait at all if the process has already exited.  Reflect movement
+       to pinfo::exit.
+
 2005-01-11  Corinna Vinschen  <corinna@vinschen.de>
 
        * environ.cc (build_env): Disallow empty strings and strings starting
index b5ce6d5..df639c2 100644 (file)
@@ -625,12 +625,8 @@ dll_crt0_0 ()
            else if (sizeof (fhandler_union) != child_proc_info->fhandler_union_cb)
              multiple_cygwin_problem ("fhandler size", child_proc_info->fhandler_union_cb, sizeof (fhandler_union));
            else
-             {
-               if (child_proc_info->type != _PROC_FORK)
-                 child_proc_info->ready (true);
-               cygwin_user_h = child_proc_info->user_h;
-               break;
-             }
+             cygwin_user_h = child_proc_info->user_h;
+           break;
          default:
            system_printf ("unknown exec type %d", child_proc_info->type);
            /* intentionally fall through */
@@ -667,6 +663,8 @@ dll_crt0_0 ()
                                  DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE))
              h = NULL;
            set_myself (h);
+           if (child_proc_info->type != _PROC_FORK)
+             child_proc_info->ready (true);
            __argc = spawn_info->moreinfo->argc;
            __argv = spawn_info->moreinfo->argv;
            envp = spawn_info->moreinfo->envp;
@@ -1060,7 +1058,7 @@ do_exit (int status)
     }
 
   minimal_printf ("winpid %d, exit %d", GetCurrentProcessId (), n);
-  myself->exit (n);
+  myself.exit (n);
 }
 
 static muto *atexit_lock;
@@ -1123,7 +1121,7 @@ __api_fatal (const char *fmt, ...)
 #ifdef DEBUGGING
   (void) try_to_debug ();
 #endif
-  myself->exit (1);
+  myself.exit (1);
 }
 
 void
index fb7923c..141afb7 100644 (file)
@@ -121,6 +121,7 @@ static NO_COPY struct
   X (DEVICE_DOOR_OPEN,         EIO),
   X (IO_PENDING,               EAGAIN),
   X (TOO_MANY_LINKS,           EMLINK),
+  X (PROC_NOT_FOUND,           ESRCH),
   { 0, NULL, 0}
 };
 
index 9993ef4..2531e6c 100644 (file)
@@ -1080,7 +1080,7 @@ signal_exit (int rc)
 {
   EnterCriticalSection (&exit_lock);
   if (exit_already++)
-    myself->exit (rc);
+    myself.exit (rc);
 
   /* We'd like to stop the main thread from executing but when we do that it
      causes random, inexplicable hangs.  So, instead, we set up the priority
index 7417f05..ad47618 100644 (file)
@@ -111,6 +111,7 @@ extern "C" int WINAPI
 dll_entry (HANDLE h, DWORD reason, void *static_load)
 {
   BOOL is_64bit_machine = FALSE;
+  extern HANDLE hExeced;
 
   switch (reason)
     {
@@ -127,8 +128,12 @@ dll_entry (HANDLE h, DWORD reason, void *static_load)
       dll_crt0_0 ();
       break;
     case DLL_PROCESS_DETACH:
-      if (myself && myself->exitcode == EXITCODE_UNSET)
-       myself->exitcode = 1 << 8;
+      if (myself)
+       {
+         if (!hExeced && myself->exitcode == EXITCODE_UNSET)
+           myself->exitcode = 1 << 8;
+         myself.release ();
+       }
       break;
     case DLL_THREAD_ATTACH:
       munge_threadfunc ();
index 8b184a6..6d55dc4 100644 (file)
@@ -39,6 +39,8 @@ static char NO_COPY pinfo_dummy[sizeof (_pinfo)] = {0};
 
 pinfo NO_COPY myself ((_pinfo *)&pinfo_dummy); // Avoid myself != NULL checks
 
+bool is_toplevel_proc;
+
 /* Initialize the process table.
    This is done once when the dll is first loaded.  */
 
@@ -101,40 +103,55 @@ pinfo_init (char **envp, int envc)
   debug_printf ("pid %d, pgid %d", myself->pid, myself->pgid);
 }
 
+# define self (*this)
 void
-_pinfo::exit (UINT n, bool norecord)
+pinfo::set_exit_state (DWORD pidstate)
+{
+  DWORD x = 0xdeadbeef;
+  DWORD oexitcode = self->exitcode;
+  if (hProcess && self->exitcode == EXITCODE_UNSET)
+    {
+      GetExitCodeProcess (hProcess, &x);
+      self->exitcode = (x & 0xff) << 8;
+    }
+  sigproc_printf ("exit value - old %p, windows %p, cygwin %p", oexitcode, x,
+                 self->exitcode);
+  if (self->exitcode != EXITCODE_NOSET)
+    self->process_state = pidstate;
+}
+
+void
+pinfo::exit (DWORD n)
 {
   exit_state = ES_FINAL;
   cygthread::terminate ();
-  if (norecord)
-    sigproc_terminate ();              /* Just terminate signal and process stuff */
-  else
-    exitcode = n;                      /* We're really exiting.  Record the UNIX exit code. */
-
-  if (this)
+  if (n != EXITCODE_EXEC)
     {
-      /* 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;
-         /* Ensure that the parent knows that this logical process has
-            terminated. */
-         myself->alert_parent (0);
-           
-       }
+      sigproc_terminate ();    /* Just terminate signal and process stuff */
+      self->exitcode = n;      /* We're really exiting.  Record the UNIX exit code. */
     }
-
-  sigproc_printf ("Calling ExitProcess norecord %d, n %p, exitcode %p",
-                 norecord, n, exitcode);
+  sigproc_printf ("1 hProcess %p, n %p, exitcode %p", hProcess, n, self->exitcode);
+
+  /* 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 (&self->rusage_self, &r);
+
+  set_exit_state (PID_EXITED);
+  sigproc_printf ("2 hProcess %p, n %p, exitcode %p, EXITCODE_EXEC %p", hProcess, n, self->exitcode, EXITCODE_EXEC);
+  if (n != EXITCODE_EXEC)
+{sigproc_printf ("3 hProcess %p, n %p, exitcode %p, EXITCODE_EXE %pC", hProcess, n, self->exitcode, EXITCODE_EXEC);
+    myself->alert_parent (0);
+}
+  
   _my_tls.stacklock = 0;
   _my_tls.stackptr = _my_tls.stack;
-  ExitProcess (exitcode);
+  sigproc_printf ("Calling ExitProcess hProcess %p, n %p, exitcode %p",
+                 hProcess, n, self->exitcode);
+  ExitProcess (self->exitcode);
 }
+# undef self
 
 void
 pinfo::init (pid_t n, DWORD flag, HANDLE in_h)
@@ -664,7 +681,6 @@ _pinfo::cmdline (size_t& n)
 static DWORD WINAPI
 proc_waiter (void *arg)
 {
-  extern HANDLE hExeced;
   pinfo& vchild = *(pinfo *) arg;
 
   siginfo_t si;
@@ -685,6 +701,8 @@ proc_waiter (void *arg)
     {
       DWORD nb;
       char buf = '\0';
+      extern HANDLE hExeced;
+
       if (!ReadFile (vchild.rd_proc_pipe, &buf, 1, &nb, NULL)
          && GetLastError () != ERROR_BROKEN_PIPE)
        {
@@ -702,12 +720,7 @@ proc_waiter (void *arg)
          /* Child exited.  Do some cleanup and signal myself.  */
          CloseHandle (vchild.rd_proc_pipe);
          vchild.rd_proc_pipe = NULL;
-         if (vchild->exitcode == EXITCODE_UNSET)
-           {
-             DWORD x;
-             GetExitCodeProcess (vchild.hProcess, &x);
-             vchild->exitcode = (x & 0xff) << 8;
-           }
+         vchild.set_exit_state (PID_ZOMBIE);
          if (WIFEXITED (vchild->exitcode))
            si.si_sigval.sival_int = CLD_EXITED;
          else if (WCOREDUMP (vchild->exitcode))
@@ -715,7 +728,6 @@ proc_waiter (void *arg)
          else
            si.si_sigval.sival_int = CLD_KILLED;
          si.si_status = vchild->exitcode;
-         vchild->process_state = PID_ZOMBIE;
          break;
        case SIGTTIN:
        case SIGTTOU:
@@ -769,7 +781,7 @@ _pinfo::dup_proc_pipe (HANDLE hProcess)
   /* Grr.  Can't set DUPLICATE_CLOSE_SOURCE for exec case because we could be
      execing a non-cygwin process and we need to set the exit value before the
      parent sees it.  */
-  if (this != myself)
+  if (this != myself || is_toplevel_proc)
     flags |= DUPLICATE_CLOSE_SOURCE;
   bool res = DuplicateHandle (hMainProc, wr_proc_pipe, hProcess, &wr_proc_pipe,
                              0, FALSE, flags);
index b649e0f..776e635 100644 (file)
@@ -27,6 +27,8 @@ enum picom
 };
 
 #define EXITCODE_UNSET 0x80000000
+#define EXITCODE_NOSET EXITCODE_UNSET
+#define EXITCODE_EXEC EXITCODE_UNSET
 
 class _pinfo
 {
@@ -83,8 +85,6 @@ public:
   HANDLE tothem;
   HANDLE fromthem;
 
-  void exit (UINT n, bool norecord = 0) __attribute__ ((noreturn, regparm(2)));
-
   inline void set_has_pgid_children ()
   {
     if (pgid == pid)
@@ -155,6 +155,8 @@ public:
     if (destroy && procinfo)
       release ();
   }
+  void exit (DWORD n) __attribute__ ((noreturn, regparm(2)));
+  void set_exit_state (DWORD) __attribute__ ((regparm(2)));
   void initialize_lock () {InitializeCriticalSection (&_lock);}
   void lock () {EnterCriticalSection (&_lock);}
   void unlock () {LeaveCriticalSection (&_lock);}
index 6ec9a28..1f65712 100644 (file)
@@ -170,7 +170,13 @@ proc_can_be_signalled (_pinfo *p)
   if (p->sendsig != INVALID_HANDLE_VALUE)
     {
       if (p == myself_nowait || p == myself)
-       return hwait_sig;
+       if (hwait_sig)
+         return true;
+       else
+         {
+           set_errno (EAGAIN);
+           return hwait_sig;
+         }
 
       if (ISSTATE (p, PID_INITIALIZING) ||
          (((p)->process_state & (PID_ACTIVE | PID_IN_USE)) ==
@@ -544,9 +550,6 @@ sig_send (_pinfo *p, siginfo_t& si, _cygtls *tls)
   sigpacket pack;
 
   pack.wakeup = NULL;
-  if (!myself->sendsig)        // FIXME: This catches the exec case but what if the exec is going to fail?
-    goto out;
-
   bool wait_for_completion;
   if (!(its_me = (p == NULL || p == myself || p == myself_nowait)))
     wait_for_completion = false;
@@ -556,6 +559,7 @@ sig_send (_pinfo *p, siginfo_t& si, _cygtls *tls)
        {
          sigproc_printf ("hwait_sig %p, myself->sendsig %p, exit_state %d",
                          hwait_sig, myself->sendsig, exit_state);
+         set_errno (EAGAIN);
          goto out;             // Either exiting or not yet initializing
        }
       if (wait_sig_inited)
@@ -601,8 +605,8 @@ sig_send (_pinfo *p, siginfo_t& si, _cygtls *tls)
       HANDLE hp = OpenProcess (PROCESS_DUP_HANDLE, false, dwProcessId);
       if (!hp)
        {
-         sigproc_printf ("OpenProcess failed, %E");
          __seterrno ();
+         sigproc_printf ("OpenProcess failed, %E");
          goto out;
        }
       VerifyHandle (hp);
@@ -651,8 +655,8 @@ sig_send (_pinfo *p, siginfo_t& si, _cygtls *tls)
         process is exiting.  */
       if (!its_me)
        {
-         sigproc_printf ("WriteFile for pipe %p failed, %E", sendsig);
          __seterrno ();
+         sigproc_printf ("WriteFile for pipe %p failed, %E", sendsig);
          ForceCloseHandle (sendsig);
        }
       else
@@ -662,6 +666,7 @@ sig_send (_pinfo *p, siginfo_t& si, _cygtls *tls)
          else if (!hExeced)
            system_printf ("error sending signal %d to pid %d, pipe handle %p, %E",
                          si.si_signo, p->pid, sendsig);
+         set_errno (EACCES);
        }
       goto out;
     }
@@ -796,15 +801,9 @@ child_info::sync (pinfo& vchild, DWORD howlong)
       res = true;
       break;
     case WAIT_OBJECT_0 + 1:
+      sigproc_printf ("process exited before subproc_ready");
       if (WaitForSingleObject (subproc_ready, 0) == WAIT_OBJECT_0)
        sigproc_printf ("should never happen.  noticed subproc_ready after process exit");
-      else
-       {
-         DWORD exitcode = 0;
-         (void) GetExitCodeProcess (vchild.hProcess, &exitcode);
-         vchild->exitcode = (exitcode & 0xff) << 8;
-         sigproc_printf ("non-cygwin exit value is %p", exitcode);
-       }
       res = false;
       break;
     default:
index e18b3e2..d41c586 100644 (file)
@@ -645,7 +645,7 @@ spawn_guts (const char * prog_arg, const char *const *argv,
      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 (wincap.start_proc_suspended() || mode != _P_OVERLAY
+  if (wincap.start_proc_suspended () || mode != _P_OVERLAY
       || cygheap->fdtab.need_fixup_before ())
     flags |= CREATE_SUSPENDED;
 
@@ -787,7 +787,7 @@ spawn_guts (const char * prog_arg, const char *const *argv,
   /* Name the handle similarly to proc_subproc. */
   ProtectHandle1 (pi.hProcess, childhProc);
 
-  bool wait_for_myself = false;
+  bool synced;
   if (mode == _P_OVERLAY)
     {
       myself->dwProcessId = dwExeced = pi.dwProcessId;
@@ -807,12 +807,7 @@ spawn_guts (const char * prog_arg, const char *const *argv,
         on this fact when we exit.  dup_proc_pipe also closes our end of the pipe.
         Note that wr_proc_pipe may also be == INVALID_HANDLE_VALUE.  That will make
         dup_proc_pipe essentially a no-op.  */
-      if (!myself->wr_proc_pipe)
-       {
-         myself.remember (false);
-         wait_for_myself = true;
-       }
-      else
+      if (myself->wr_proc_pipe)
        {
          /* Make sure that we own wr_proc_pipe just in case we've been
             previously execed. */
@@ -855,42 +850,51 @@ spawn_guts (const char * prog_arg, const char *const *argv,
        }
     }
 
-/* Start the child running */
-if (flags & CREATE_SUSPENDED)
-  ResumeThread (pi.hThread);
-ForceCloseHandle (pi.hThread);
+  /* Start the child running */
+  if (flags & CREATE_SUSPENDED)
+    ResumeThread (pi.hThread);
+  ForceCloseHandle (pi.hThread);
 
-sigproc_printf ("spawned windows pid %d", pi.dwProcessId);
+  sigproc_printf ("spawned windows pid %d", pi.dwProcessId);
 
-ciresrv.sync (myself, INFINITE);
+  synced = ciresrv.sync (myself, INFINITE);
 
-switch (mode)
-  {
-  case _P_OVERLAY:
-    if (wait_for_myself)
-      waitpid (myself->pid, &res, 0);
-    myself->exit (res, 1);
-    break;
-  case _P_WAIT:
-  case _P_SYSTEM:
-    if (waitpid (cygpid, (int *) &res, 0) != cygpid)
-      res = -1;
-    break;
-  case _P_DETACH:
-    res = 0;   /* Lost all memory of this child. */
-    break;
-  case _P_NOWAIT:
-  case _P_NOWAITO:
-  case _P_VFORK:
-    res = cygpid;
-    break;
-  default:
-    break;
-  }
+  switch (mode)
+    {
+    case _P_OVERLAY:
+      if (!synced)
+       /* let myself.exit handle this */;
+      else if (myself->wr_proc_pipe)
+       myself.hProcess = NULL;
+      else
+       {
+         extern bool is_toplevel_proc;
+         is_toplevel_proc = true;
+         myself.remember (false);
+         waitpid (myself->pid, &res, 0);
+       }
+      myself.exit (EXITCODE_EXEC);
+      break;
+    case _P_WAIT:
+    case _P_SYSTEM:
+      if (waitpid (cygpid, &res, 0) != cygpid)
+       res = -1;
+      break;
+    case _P_DETACH:
+      res = 0; /* Lost all memory of this child. */
+      break;
+    case _P_NOWAIT:
+    case _P_NOWAITO:
+    case _P_VFORK:
+      res = cygpid;
+      break;
+    default:
+      break;
+    }
 
 out:
-pthread_cleanup_pop (1);
-return (int) res;
+  pthread_cleanup_pop (1);
+  return (int) res;
 }
 
 extern "C" int
index 4c0f08e..960a894 100644 (file)
@@ -125,7 +125,7 @@ strace::vsprntf (char *buf, const char *func, const char *infmt, va_list ap)
   int microsec = microseconds ();
   lmicrosec = microsec;
 
-  __small_sprintf (fmt, "%7d [%s] %s ", microsec, tn, "%s %d%s");
+  __small_sprintf (fmt, "%7d [%s] %s ", microsec, tn, "%s %d/%d%s");
 
   SetLastError (err);
 
@@ -147,7 +147,7 @@ strace::vsprntf (char *buf, const char *func, const char *infmt, va_list ap)
        *p = '\000';
       p = progname;
       count = __small_sprintf (buf, fmt, p && *p ? p : "?",
-                              myself->pid ?: GetCurrentProcessId (),
+                              myself->pid ?: GetCurrentProcessId (), GetCurrentProcessId (),
                               execing ? "!" : "");
       if (func)
        count += getfunc (buf + count, func);