OSDN Git Service

* child_info.h (child_info): Add pppid_handle for closing the parent's of the
authorcgf <cgf>
Mon, 6 Nov 2000 06:36:32 +0000 (06:36 +0000)
committercgf <cgf>
Mon, 6 Nov 2000 06:36:32 +0000 (06:36 +0000)
parent handle.
* dcrt0.cc (_dll_crt0): Close parent's parent handle when spawned or forked.
* debug.cc (add_handle): Correct erroneous reference to handle structure when
printing warning.
* exceptions.cc (interrupt_now): Always return 1.
(interrupt_on_return): Accept a sigthread argument.  Check to see if this
argument has been trashed prior to setting up the stack return.
(call_handler): Add a loop around attempts to dispatch signals to detect case
where interrupt_on_return fails.
(_sigdelayed): Set up a temporary frame pointer prior to calling stuff that
could trigger an interrupt or the stack walking code will be very confused.
* fork.cc (fork_parent): Move a lot of the setup of the child process into
proc_subproc.
* spawn.cc (spawn_guts): Ditto.  Use ppid_handle to contact logical parent when
reparenting.
* pinfo.h (_pinfo): Remember the logical handle of the parent process.
* sigproc.cc (proc_subproc): Record most stuff necessary for the _pinfo
structure that is inferrable from myself when adding children.
(wait_sig): Always set 'pending_signals' flag when about to kick off the signal
scanning loop.  Reset it only if there are no pending signals.

winsup/cygwin/ChangeLog
winsup/cygwin/child_info.h
winsup/cygwin/dcrt0.cc
winsup/cygwin/debug.cc
winsup/cygwin/exceptions.cc
winsup/cygwin/fork.cc
winsup/cygwin/pinfo.h
winsup/cygwin/sigproc.cc
winsup/cygwin/spawn.cc

index ea14744..a7e48ed 100644 (file)
@@ -1,3 +1,30 @@
+Mon Nov  6 01:04:35 2000  Christopher Faylor <cgf@cygnus.com>
+
+       * child_info.h (child_info): Add pppid_handle for closing the parent's
+       of the parent handle.
+       * dcrt0.cc (_dll_crt0): Close parent's parent handle when spawned or
+       forked.
+       * debug.cc (add_handle): Correct erroneous reference to handle
+       structure when printing warning.
+       * exceptions.cc (interrupt_now): Always return 1.
+       (interrupt_on_return): Accept a sigthread argument.  Check to see if
+       this argument has been trashed prior to setting up the stack return.
+       (call_handler): Add a loop around attempts to dispatch signals to
+       detect case where interrupt_on_return fails.
+       (_sigdelayed): Set up a temporary frame pointer prior to calling stuff
+       that could trigger an interrupt or the stack walking code will be very
+       confused.
+       * fork.cc (fork_parent): Move a lot of the setup of the child process
+       into proc_subproc.
+       * spawn.cc (spawn_guts): Ditto.  Use ppid_handle to contact logical
+       parent when reparenting.
+       * pinfo.h (_pinfo): Remember the logical handle of the parent process.
+       * sigproc.cc (proc_subproc): Record most stuff necessary for the _pinfo
+       structure that is inferrable from myself when adding children.
+       (wait_sig): Always set 'pending_signals' flag when about to kick off
+       the signal scanning loop.  Reset it only if there are no pending
+       signals.
+
 Sun Nov  5 13:46:23 2000  Christopher Faylor <cgf@cygnus.com>
 
        * pinfo (wait_subproc): Son of neverending debug tweaking.
index 7258330..9249247 100644 (file)
@@ -12,7 +12,7 @@ details. */
 
 enum
 {
-  PROC_MAGIC = 0xaf09f000,
+  PROC_MAGIC = 0xaf0af000,
   PROC_FORK = PROC_MAGIC + 1,
   PROC_EXEC = PROC_MAGIC + 2,
   PROC_SPAWN = PROC_MAGIC + 3,
@@ -38,6 +38,7 @@ public:
   HANDLE console_h;
   HANDLE parent_alive; // handle of thread used to track children
   HANDLE parent;
+  HANDLE pppid_handle;
   void *cygheap;
   void *cygheap_max;
 };
index 56873b1..faa7cfa 100644 (file)
@@ -898,8 +898,9 @@ _dll_crt0 ()
          case PROC_FORK:
          case PROC_FORK1:
            user_data->forkee = fork_info->cygpid;
-         case PROC_EXEC:
          case PROC_SPAWN:
+           CloseHandle (fork_info->pppid_handle);
+         case PROC_EXEC:
            {
              child_proc_info = fork_info;
              mypid = child_proc_info->cygpid;
index e25dc1c..ebe207c 100644 (file)
@@ -228,7 +228,7 @@ newh ()
       goto out;
 
   /* All used up??? */
-  if ((hl = (handle_list *)malloc (sizeof *hl)) != NULL)
+  if ((hl = (handle_list *) malloc (sizeof *hl)) != NULL)
     {
       memset (hl, 0, sizeof (*hl));
       hl->allocated = TRUE;
@@ -248,6 +248,7 @@ add_handle (const char *func, int ln, HANDLE h, const char *name)
 
   if ((hl = find_handle (h)))
     {
+      hl = hl->next;
       system_printf ("%s:%d - multiple attempts to add handle %s<%p>", func,
                     ln, name, h);
       system_printf (" previously allocated by %s:%d(%s<%p>)",
index 5fa5889..4358e6a 100644 (file)
@@ -30,6 +30,7 @@ static int handle_exceptions (EXCEPTION_RECORD *, void *, CONTEXT *, void *);
 extern void sigreturn ();
 extern void sigdelayed ();
 extern void siglast ();
+extern DWORD __no_sig_start, __no_sig_end;
 };
 
 extern DWORD sigtid;
@@ -627,12 +628,13 @@ interrupt_setup (int sig, struct sigaction& siga, void *handler,
   sigsave.saved_errno = -1;            // Flag: no errno to save
 }
 
-static void
+static bool
 interrupt_now (CONTEXT *ctx, int sig, struct sigaction& siga, void *handler)
 {
   interrupt_setup (sig, siga, handler, ctx->Eip, 0);
   ctx->Eip = (DWORD) sigdelayed;
   SetThreadContext (myself->getthread2signal (), ctx); /* Restart the thread */
+  return 1;
 }
 
 void __stdcall
@@ -662,12 +664,13 @@ signal_fixup_after_exec (bool isspawn)
 }
 
 static int
-interrupt_on_return (DWORD ebp, int sig, struct sigaction& siga, void *handler)
+interrupt_on_return (sigthread *th, int sig, struct sigaction& siga, void *handler)
 {
   int i;
+  DWORD ebp = th->frame;
 
-  if (sigsave.sig)
-    return 0;  /* Already have a signal stacked up */
+  if (!ebp)
+    return 0;
 
   thestack.init (ebp);  /* Initialize from the input CONTEXT */
   for (i = 0; i < 32 && thestack++ ; i++)
@@ -677,12 +680,16 @@ interrupt_on_return (DWORD ebp, int sig, struct sigaction& siga, void *handler)
        if (*addr_retaddr  == thestack.sf.AddrReturn.Offset)
          {
            interrupt_setup (sig, siga, handler, *addr_retaddr, addr_retaddr);
+           if (ebp != th->frame)
+             {
+               sigsave.sig = 0;
+               break;
+             }
            *addr_retaddr = (DWORD) sigdelayed;
          }
        return 1;
       }
 
-  api_fatal ("couldn't send signal %d", sig);
   return 0;
 }
 
@@ -700,11 +707,10 @@ static int
 call_handler (int sig, struct sigaction& siga, void *handler)
 {
   CONTEXT cx;
-  int interrupted = 1;
+  bool interrupted = 0;
   HANDLE hth = NULL;
-  DWORD ebp;
   int res;
-  int using_mainthread_frame;
+  sigthread *th;
 
 #if 0
   mainthread.lock->acquire ();
@@ -713,98 +719,101 @@ call_handler (int sig, struct sigaction& siga, void *handler)
   if (sigsave.sig)
     goto set_pending;
 
-  if (mainthread.frame)
+  for (int i = 0; !interrupted && i < 10; i++)
     {
-      ebp = mainthread.frame;
-      using_mainthread_frame = 1;
-    }
-  else
-    {
-      int i;
-      using_mainthread_frame = 0;
-#if 0
-      mainthread.lock->release ();
-#endif
-
-      hth = myself->getthread2signal ();
-      /* Suspend the thread which will receive the signal.  But first ensure that
-        this thread doesn't have any mutos.  (FIXME: Someday we should just grab
-        all of the mutos rather than checking for them)
-        For Windows 95, we also have to ensure that the addresses returned by GetThreadContext
-        are valid.
-        If one of these conditions is not true we loop for a fixed number of times
-        since we don't want to stall the signal handler.  FIXME: Will this result in
-        noticeable delays?
-        If the thread is already suspended (which can occur when a program is stopped) then
-        just queue the signal. */
-      for (i = 0; i < SUSPEND_TRIES; i++)
+      if (mainthread.frame)
+       th = &mainthread;
+      else
        {
-         sigproc_printf ("suspending mainthread");
-         res = SuspendThread (hth);
-
-         muto *m;
-         /* FIXME: Make multi-thread aware */
-         for (m = muto_start.next;  m != NULL; m = m->next)
-           if (m->unstable () || m->owner () == mainthread.id)
-             goto owns_muto;
-
-#if 0
-         mainthread.lock->acquire ();
-#endif
-         if (mainthread.frame)
-           {
-             ebp = mainthread.frame;   /* try to avoid a race */
-             using_mainthread_frame = 1;
-             goto next;
-           }
-#if 0
+         int i;
+         th = NULL;
+    #if 0
          mainthread.lock->release ();
-#endif
-
-         cx.ContextFlags = CONTEXT_CONTROL | CONTEXT_INTEGER;
-         if (!GetThreadContext (hth, &cx))
+    #endif
+
+         hth = myself->getthread2signal ();
+         /* Suspend the thread which will receive the signal.  But first ensure that
+            this thread doesn't have any mutos.  (FIXME: Someday we should just grab
+            all of the mutos rather than checking for them)
+            For Windows 95, we also have to ensure that the addresses returned by GetThreadContext
+            are valid.
+            If one of these conditions is not true we loop for a fixed number of times
+            since we don't want to stall the signal handler.  FIXME: Will this result in
+            noticeable delays?
+            If the thread is already suspended (which can occur when a program is stopped) then
+            just queue the signal. */
+         for (i = 0; i < SUSPEND_TRIES; i++)
            {
-             system_printf ("couldn't get context of main thread, %E");
-             goto out;
-           }
+             sigproc_printf ("suspending mainthread");
+             res = SuspendThread (hth);
+
+             /* Just set pending if thread is already suspended */
+             if (res)
+               goto set_pending;
+
+             muto *m;
+             /* FIXME: Make multi-thread aware */
+             for (m = muto_start.next;  m != NULL; m = m->next)
+               if (m->unstable () || m->owner () == mainthread.id)
+                 goto owns_muto;
+
+    #if 0
+             mainthread.lock->acquire ();
+    #endif
+             if (mainthread.frame)
+               {
+                 th = &mainthread;
+                 goto next;
+               }
+    #if 0
+             mainthread.lock->release ();
+    #endif
+
+             cx.ContextFlags = CONTEXT_CONTROL | CONTEXT_INTEGER;
+             if (!GetThreadContext (hth, &cx))
+               {
+                 system_printf ("couldn't get context of main thread, %E");
+                 goto out;
+               }
+
+             if (interruptible (cx.Eip, 1))
+               break;
 
-         if (interruptible (cx.Eip, 1))
-           break;
+             sigproc_printf ("suspended thread in a strange state pc %p, sp %p",
+                             cx.Eip, cx.Esp);
+             goto resume_thread;
 
-         sigproc_printf ("suspended thread in a strange state pc %p, sp %p",
-                         cx.Eip, cx.Esp);
-         goto resume_thread;
+           owns_muto:
+             sigproc_printf ("suspended thread owns a muto (%s)", m->name);
 
-       owns_muto:
-         sigproc_printf ("suspended thread owns a muto (%s)", m->name);
+           resume_thread:
+             ResumeThread (hth);
+             Sleep (0);
+           }
 
-         if (res)
+         if (i >= SUSPEND_TRIES)
            goto set_pending;
 
-       resume_thread:
-         ResumeThread (hth);
-         Sleep (0);
+         sigproc_printf ("SuspendThread returned %d", res);
        }
 
-      if (i >= SUSPEND_TRIES)
-       goto set_pending;
-
-      sigproc_printf ("SuspendThread returned %d", res);
-      ebp = cx.Ebp;
+    next:
+      if (th)
+       interrupted = interrupt_on_return (th, sig, siga, handler);
+      else if (interruptible (cx.Eip))
+       interrupted = interrupt_now (&cx, sig, siga, handler);
+      else
+       break;
     }
 
-next:
-  if (!using_mainthread_frame && interruptible (cx.Eip))
-    interrupt_now (&cx, sig, siga, handler);
-  else if (!interrupt_on_return (ebp, sig, siga, handler))
+set_pending:
+  if (!interrupted)
     {
-    set_pending:
       pending_signals = 1;     /* FIXME: Probably need to be more tricky here */
       sig_set_pending (sig);
-      interrupted = 0;
+      sigproc_printf ("couldn't send signal %d", sig);
     }
-
-  if (interrupted)
+  else
     {
       res = SetEvent (signal_arrived); // For an EINTR case
       sigproc_printf ("armed signal_arrived %p, res %d", signal_arrived, res);
@@ -882,6 +891,9 @@ set_process_mask (sigset_t newmask)
   mask_sync->release ();
   if (oldmask != newmask && GetCurrentThreadId () != sigtid)
     sig_dispatch_pending ();
+  else
+    sigproc_printf ("not calling sig_dispatch_pending.  sigtid %p current %p",
+                   sigtid, GetCurrentThreadId ());
   return;
 }
 
@@ -1099,7 +1111,7 @@ __asm__ volatile ("
        .text
 
 _sigreturn:
-       addl    $4,%%esp
+       addl    $4,%%esp        # Remove argument
        movl    %%esp,%%ebp
        addl    $36,%%ebp
        call    _set_process_mask@4
@@ -1118,6 +1130,7 @@ _sigreturn:
        popf
        ret
 
+__no_sig_start:
 _sigdelayed:
        pushl   %2      # original return address
        pushf
@@ -1132,6 +1145,8 @@ _sigdelayed:
        pushl   %3      # oldmask
        pushl   %4      # signal argument
        pushl   $_sigreturn
+       pushl   %%ebp
+       movl    %%esp,%%esp
 
        call    _reset_signal_arrived@0
        movl    $0,%0
@@ -1141,7 +1156,9 @@ _sigdelayed:
        pushl   $0
        call    _sig_dispatch_pending@4
 
-2:     jmp     *%5
+2:     popl    %%ebp
+       jmp     *%5
+__no_sig_end:
 
 " : "=m" (sigsave.sig) : "m" (&_impure_ptr->_errno),
   "g" (sigsave.retaddr), "g" (sigsave.oldmask), "g" (sigsave.sig),
index 87315a4..c5536e2 100644 (file)
@@ -471,35 +471,12 @@ fork_parent (void *stack_here, HANDLE& hParent, dll *&first_dll, bool& load_dlls
     system_printf ("couldn't create last_fork_proc, %E");
 
   /* Fill in fields in the child's process table entry.  */
-  forked->ppid = myself->pid;
   forked->hProcess = pi.hProcess;
   forked->dwProcessId = pi.dwProcessId;
-  forked->uid = myself->uid;
-  forked->gid = myself->gid;
-  forked->pgid = myself->pgid;
-  forked->sid = myself->sid;
-  forked->ctty = myself->ctty;
-  forked->umask = myself->umask;
   forked->copysigs(myself);
-  forked->process_state |= PID_INITIALIZING |
-                         (myself->process_state & PID_USETTY);
   memcpy (forked->username, myself->username, MAX_USER_NAME);
-  if (myself->use_psid)
-    {
-      memcpy (forked->psid, myself->psid, MAX_SID_LEN);
-      forked->use_psid = 1;
-    }
-  memcpy (forked->logsrv, myself->logsrv, MAX_HOST_NAME);
-  memcpy (forked->domain, myself->domain, MAX_COMPUTERNAME_LENGTH+1);
-  forked->token = myself->token;
-  forked->impersonated = myself->impersonated;
-  forked->orig_uid = myself->orig_uid;
-  forked->orig_gid = myself->orig_gid;
-  forked->real_uid = myself->real_uid;
-  forked->real_gid = myself->real_gid;
-  strcpy (forked->root, myself->root);
-  forked->rootlen = myself->rootlen;
   set_child_mmap_ptr (forked);
+  forked.remember ();
 
   /* Wait for subproc to initialize itself. */
   if (!sync_with_child(pi, subproc_ready, TRUE, "waiting for longjmp"))
@@ -536,8 +513,6 @@ fork_parent (void *stack_here, HANDLE& hParent, dll *&first_dll, bool& load_dlls
        goto cleanup;
     }
 
-  forked.remember ();
-
   /* Start thread, and wait for it to reload dlls.  */
   if (!resume_child (pi, forker_finished) ||
       !sync_with_child (pi, subproc_ready, load_dlls, "child loading dlls"))
index b078c9b..2ff4ba5 100644 (file)
@@ -44,6 +44,9 @@ public:
   /* Handle associated with initial Windows pid which started it all. */
   HANDLE pid_handle;
 
+  /* Handle to the logical parent of this pid. */
+  HANDLE ppid_handle;
+
   /* Parent process id.  */
   pid_t ppid;
 
index 24fe1d0..81ba58b 100644 (file)
@@ -235,7 +235,7 @@ proc_subproc (DWORD what, DWORD val)
 
   if (!get_proc_lock (what, val))      // Serialize access to this function
     {
-      sigproc_printf ("I am not ready");
+      system_printf ("couldn't get proc lock.  Something is wrong.");
       goto out1;
     }
 
@@ -253,6 +253,33 @@ proc_subproc (DWORD what, DWORD val)
                            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,
+                           0, TRUE, DUPLICATE_SAME_ACCESS))
+       system_printf ("Couldn't duplicate my handle<%p> for pid %d, %E", hMainProc, vchild->pid);
+      vchild->ppid = myself->pid;
+      vchild->gid = myself->gid;
+      vchild->pgid = myself->pgid;
+      vchild->sid = myself->sid;
+      vchild->ctty = myself->ctty;
+      vchild->umask = myself->umask;
+      vchild->orig_uid = myself->orig_uid;
+      vchild->orig_gid = myself->orig_gid;
+      vchild->real_uid = myself->real_uid;
+      vchild->real_gid = myself->real_gid;
+      vchild->impersonated = myself->impersonated;
+      if (myself->use_psid)
+        {
+          vchild->use_psid = 1;
+          memcpy (vchild->psid, myself->psid, MAX_SID_LEN);
+        }
+      memcpy (vchild->logsrv, myself->logsrv, MAX_HOST_NAME);
+      memcpy (vchild->domain, myself->domain, MAX_COMPUTERNAME_LENGTH+1);
+      memcpy (vchild->root, myself->root, MAX_PATH+1);
+      vchild->token = myself->token;
+      vchild->rootlen = myself->rootlen;
+      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);
@@ -810,6 +837,7 @@ init_child_info (DWORD chtype, child_info *ch, pid_t pid, HANDLE subproc_ready)
   ch->shared_h = cygwin_shared_h;
   ch->console_h = console_shared_h;
   ch->subproc_ready = subproc_ready;
+  ch->pppid_handle = myself->ppid_handle;
   if (chtype != PROC_EXEC || !parent_alive)
     ch->parent_alive = hwait_subproc;
   else
@@ -1100,7 +1128,7 @@ wait_sig (VOID *)
 
   HANDLE catchem[] = {sigcatch_main, sigcatch_nonmain, sigcatch_nosync};
   sigproc_printf ("Ready.  dwProcessid %d", myself->dwProcessId);
-  for (;;)
+  for (int i = 0; ; i++)
     {
       DWORD rc = WaitForMultipleObjects (3, catchem, FALSE, sig_loop_wait);
 
@@ -1128,7 +1156,8 @@ wait_sig (VOID *)
       /* A sigcatch semaphore has been signaled.  Scan the sigtodo
        * array looking for any unprocessed signals.
        */
-      pending_signals = 0;
+      pending_signals = -1;
+      int saw_pending_signals = 0;
       int saw_sigchld = 0;
       int dispatched_sigchld = 0;
       for (int sig = -__SIGOFFSET; sig < NSIG; sig++)
@@ -1179,11 +1208,26 @@ wait_sig (VOID *)
            }
          /* Decremented too far. */
          if (InterlockedIncrement (myself->getsigtodo(sig)) > 0)
-           pending_signals = 1;
+           saw_pending_signals = 1;
        nextsig:
          continue;
        }
 
+      /* FIXME: The dispatched stuff probably isn't needed anymore. */
+      if (dispatched >= 0 && pending_signals < 0 && !saw_pending_signals)
+       {
+         pending_signals = 0;
+         /* FIXME FIXME FIXME FIXME FIXME
+            This is a real kludge designed to handle runaway processes who
+            missed a signal and never processed a signal handler.  We have
+            to reset signal_arrived or stuff goes crazy. */
+         if (i >= 20)
+           {
+             i = 0;
+             ResetEvent (signal_arrived);
+           }
+       }
+
       if (nzombies && saw_sigchld && !dispatched_sigchld)
        proc_subproc (PROC_CLEARWAIT, 0);
       /* Signal completion of signal handling depending on which semaphore
@@ -1202,8 +1246,6 @@ wait_sig (VOID *)
          break;
        }
 
-      if (dispatched < 0)
-       pending_signals = 1;
       sigproc_printf ("looping");
     }
 
@@ -1258,7 +1300,6 @@ wait_subproc (VOID *)
                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);
-               Sleep (10000);
              }
          break;
        }
index a430cf9..8e2e490 100644 (file)
@@ -707,22 +707,6 @@ skip_arg_parsing:
        }
       child->username[0] = '\0';
       child->progname[0] = '\0';
-      child->ppid = myself->pid;
-      child->gid = myself->gid;
-      child->pgid = myself->pgid;
-      child->sid = myself->sid;
-      child->ctty = myself->ctty;
-      child->umask = myself->umask;
-      child->process_state |= PID_INITIALIZING;
-      if (myself->use_psid)
-       {
-         child->use_psid = 1;
-         memcpy (child->psid, myself->psid, MAX_SID_LEN);
-       }
-      memcpy (child->logsrv, myself->logsrv, MAX_HOST_NAME);
-      memcpy (child->domain, myself->domain, MAX_COMPUTERNAME_LENGTH+1);
-      memcpy (child->root, myself->root, MAX_PATH+1);
-      child->rootlen = myself->rootlen;
       child->dwProcessId = pi.dwProcessId;
       child->hProcess = pi.hProcess;
       child.remember ();
@@ -808,20 +792,17 @@ skip_arg_parsing:
        {
          int rc = 0;
          HANDLE oldh = myself->hProcess;
-         HANDLE h = OpenProcess (PROCESS_ALL_ACCESS, FALSE,
-                                 parent->dwProcessId);
+         HANDLE h = myself->ppid_handle;
          sigproc_printf ("parent handle %p, pid %d", h, parent->dwProcessId);
          if (h == NULL && GetLastError () == ERROR_INVALID_PARAMETER)
-           rc = 1;
+           rc = 0;
          else if (h)
            {
-             ProtectHandle (h);
              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);
-             ForceCloseHandle (h);
            }
          if (!rc)
            {