OSDN Git Service

* exceptions.cc (interruptible): Remove obsolete tests.
[pf3gnuchains/pf3gnuchains3x.git] / winsup / cygwin / exceptions.cc
index 8b208b9..88b1957 100644 (file)
@@ -18,8 +18,10 @@ details. */
 #include "sigproc.h"
 #include "pinfo.h"
 #include "cygerrno.h"
-#include "thread.h"
 #include "perthread.h"
+#include "shared_info.h"
+#include "perprocess.h"
+#include "security.h"
 
 char debugger_command[2 * MAX_PATH + 20];
 
@@ -28,9 +30,10 @@ static int handle_exceptions (EXCEPTION_RECORD *, void *, CONTEXT *, void *);
 extern void sigreturn ();
 extern void sigdelayed ();
 extern void siglast ();
-extern DWORD __sigfirst, __siglast;
 };
 
+extern DWORD sigtid;
+
 static BOOL WINAPI ctrl_c_handler (DWORD);
 static void signal_exit (int) __attribute__ ((noreturn));
 static char windows_system_directory[1024];
@@ -42,7 +45,6 @@ static NO_COPY int exit_already = 0;
 static NO_COPY muto *mask_sync = NULL;
 
 HMODULE NO_COPY cygwin_hmodule;
-HANDLE NO_COPY console_handler_thread_waiter = NULL;
 
 static const struct
 {
@@ -121,10 +123,6 @@ set_console_handler ()
   sec_all.lpSecurityDescriptor = sec_all_nih.lpSecurityDescriptor =
     get_null_sd ();
 
-  /* Allocate the event needed for ctrl_c_handler synchronization with
-     wait_sig. */
-  if (!console_handler_thread_waiter)
-    CreateEvent (&sec_none_nih, TRUE, TRUE, NULL);
   (void) SetConsoleCtrlHandler (ctrl_c_handler, FALSE);
   if (!SetConsoleCtrlHandler (ctrl_c_handler, TRUE))
     system_printf ("SetConsoleCtrlHandler failed, %E");
@@ -217,7 +215,7 @@ public:
 
 /* This is the main stack frame info for this process. */
 static NO_COPY stack_info thestack;
-signal_dispatch sigsave;
+static signal_dispatch sigsave;
 
 /* Initialize everything needed to start iterating. */
 void
@@ -380,7 +378,7 @@ try_to_debug ()
 static void
 stackdump (EXCEPTION_RECORD *e, CONTEXT *in)
 {
-  char *p;
+  const char *p;
   if (myself->progname[0])
     {
       /* write to progname.stackdump if possible */
@@ -488,6 +486,7 @@ handle_exceptions (EXCEPTION_RECORD *e, void *, CONTEXT *in, void *)
       }
 
   if (!myself->progname[0]
+      || GetCurrentThreadId () == sigtid
       || (void *) myself->getsig (sig).sa_handler == (void *) SIG_DFL
       || (void *) myself->getsig (sig).sa_handler == (void *) SIG_IGN
       || (void *) myself->getsig (sig).sa_handler == (void *) SIG_ERR)
@@ -580,37 +579,34 @@ int
 interruptible (DWORD pc, int testvalid = 0)
 {
   int res;
-  if ((pc >= (DWORD) &__sigfirst) && (pc <= (DWORD) &__siglast))
+  MEMORY_BASIC_INFORMATION m;
+
+  memset (&m, 0, sizeof m);
+  if (!VirtualQuery ((LPCVOID) pc, &m, sizeof m))
+    sigproc_printf ("couldn't get memory info, pc %p, %E", pc);
+
+  char *checkdir = (char *) alloca (windows_system_directory_length + 4);
+  memset (checkdir, 0, sizeof (checkdir));
+
+# define h ((HMODULE) m.AllocationBase)
+  /* Apparently Windows 95 can sometimes return bogus addresses from
+     GetThreadContext.  These resolve to an allocation base == 0.
+     These should *never* be treated as interruptible. */
+  if (!h || m.State != MEM_COMMIT)
+    res = 0;
+  else if (testvalid)
+    res = 1;   /* All we wanted to know was if this was a valid module. */
+  else if (h == user_data->hmodule)
+    res = 1;
+  else if (h == cygwin_hmodule)
+    res = 0;
+  else if (!GetModuleFileName (h, checkdir, windows_system_directory_length + 2))
     res = 0;
   else
-    {
-      MEMORY_BASIC_INFORMATION m;
-      memset (&m, 0, sizeof m);
-      if (!VirtualQuery ((LPCVOID) pc, &m, sizeof m))
-       sigproc_printf ("couldn't get memory info, %E");
-
-      char *checkdir = (char *) alloca (windows_system_directory_length + 4);
-      memset (checkdir, 0, sizeof (checkdir));
-#     define h ((HMODULE) m.AllocationBase)
-      /* Apparently Windows 95 can sometimes return bogus addresses from
-        GetThreadContext.  These resolve to an allocation base == 0.
-        These should *never* be treated as interruptible. */
-      if (!h)
-       res = 0;
-      else if (testvalid)
-       res = 1;        /* All we wanted to know was if this was a valid module. */
-      else if (h == user_data->hmodule)
-       res = 1;
-      else if (h == cygwin_hmodule)
-       res = 0;
-      else if (!GetModuleFileName (h, checkdir, windows_system_directory_length + 2))
-       res = 0;
-      else
-       res = !strncasematch (windows_system_directory, checkdir,
-                             windows_system_directory_length);
-      minimal_printf ("h %p", h);
-#     undef h
-    }
+    res = !strncasematch (windows_system_directory, checkdir,
+                         windows_system_directory_length);
+  minimal_printf ("h %p", h);
+# undef h
 
   minimal_printf ("interruptible %d", res);
   return res;
@@ -638,7 +634,7 @@ interrupt_now (CONTEXT *ctx, int sig, struct sigaction& siga, void *handler)
   SetThreadContext (myself->getthread2signal (), ctx); /* Restart the thread */
 }
 
-void __cdecl
+void __stdcall
 signal_fixup_after_fork ()
 {
   if (!sigsave.sig)
@@ -652,6 +648,18 @@ signal_fixup_after_fork ()
     }
 }
 
+void __stdcall
+signal_fixup_after_exec (bool isspawn)
+{
+  /* Set up child's signal handlers */
+  for (int i = 0; i < NSIG; i++)
+    {
+      myself->getsig(i).sa_mask = 0;
+      if (myself->getsig(i).sa_handler != SIG_IGN || isspawn)
+       myself->getsig(i).sa_handler = SIG_DFL;
+    }
+}
+
 static int
 interrupt_on_return (DWORD ebp, int sig, struct sigaction& siga, void *handler)
 {
@@ -682,7 +690,7 @@ set_sig_errno (int e)
 {
   set_errno (e);
   sigsave.saved_errno = e;
-  debug_printf ("errno %d", e);
+  // sigproc_printf ("errno %d", e);
 }
 
 #define SUSPEND_TRIES 10000
@@ -697,7 +705,12 @@ call_handler (int sig, struct sigaction& siga, void *handler)
   int res;
   int using_mainthread_frame;
 
+#if 0
   mainthread.lock->acquire ();
+#endif
+
+  if (sigsave.sig)
+    goto set_pending;
 
   if (mainthread.frame)
     {
@@ -708,7 +721,9 @@ call_handler (int sig, struct sigaction& siga, void *handler)
     {
       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
@@ -732,14 +747,18 @@ call_handler (int sig, struct sigaction& siga, void *handler)
            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
          mainthread.lock->release ();
+#endif
 
          cx.ContextFlags = CONTEXT_CONTROL | CONTEXT_INTEGER;
          if (!GetThreadContext (hth, &cx))
@@ -774,7 +793,7 @@ call_handler (int sig, struct sigaction& siga, void *handler)
     }
 
 next:
-  if (hExeced != NULL || (!using_mainthread_frame && interruptible (cx.Eip)))
+  if (!using_mainthread_frame && interruptible (cx.Eip))
     interrupt_now (&cx, sig, siga, handler);
   else if (!interrupt_on_return (ebp, sig, siga, handler))
     {
@@ -801,7 +820,9 @@ out:
       sigproc_printf ("ResumeThread returned %d", res);
     }
 
+#if 0
   mainthread.lock->release ();
+#endif
 
   sigproc_printf ("returning %d", interrupted);
   return interrupted;
@@ -819,11 +840,6 @@ ctrl_c_handler (DWORD type)
   if (type == CTRL_LOGOFF_EVENT)
     return TRUE;
 
-  /* Wait for sigproc_init to tell us that it's safe to send something.
-     This event will always be in a signalled state when wait_sig is
-     ready to process signals. */
-  (void) WaitForSingleObject (console_handler_thread_waiter, 5000);
-
   if ((type == CTRL_CLOSE_EVENT) || (type == CTRL_SHUTDOWN_EVENT))
     /* Return FALSE to prevent an "End task" dialog box from appearing
        for each Cygwin process window that's open when the computer
@@ -856,8 +872,6 @@ ctrl_c_handler (DWORD type)
 extern "C" void __stdcall
 set_process_mask (sigset_t newmask)
 {
-  extern DWORD sigtid;
-
   mask_sync->acquire (INFINITE);
   sigset_t oldmask = myself->getsigmask ();
   newmask &= ~SIG_NONMASKABLE;
@@ -929,7 +943,7 @@ sig_handle (int sig)
       while (ResumeThread (hMainThread) > 1)
        ;
       /* process pending signals */
-      sig_dispatch_pending ();
+      sig_dispatch_pending (1);
     }
 
 #if 0
@@ -989,11 +1003,6 @@ exit_sig:
       sig |= 0x80;
     }
   sigproc_printf ("signal %d, about to call do_exit", sig);
-  TerminateThread (hMainThread, 0);
-  /* FIXME: This just works around the problem so that we don't attempt to
-     use a resource lock when exiting.  */
-  user_data->resourcelocks->Delete ();
-  user_data->resourcelocks->Init ();
   signal_exit (sig);
   /* Never returns */
 }
@@ -1004,17 +1013,30 @@ exit_sig:
 static void
 signal_exit (int rc)
 {
-  /* If the exception handler gets a trap, we could recurse awhile.
-     If this is non-zero, skip the cleaning up and exit NOW.  */
+  extern HANDLE hExeced;
 
   rc = EXIT_SIGNAL | (rc << 8);
   if (exit_already++)
-    {
-      /* We are going down - reset our process_state without locking. */
-      myself->record_death ();
-      ExitProcess (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
+     of this thread really high so that it should do its thing and then exit. */
+  (void) SetThreadPriority (GetCurrentThread (), THREAD_PRIORITY_TIME_CRITICAL);
 
+  /* Unlock any main thread mutos since we're executing with prejudice. */
+  muto *m;
+  for (m = muto_start.next;  m != NULL; m = m->next)
+    if (m->unstable () || m->owner () == mainthread.id)
+      m->reset ();
+
+  user_data->resourcelocks->Delete ();
+  user_data->resourcelocks->Init ();
+
+  if (hExeced)
+    TerminateProcess (hExeced, rc);
+
+  sigproc_printf ("about to call do_exit (%x)", rc);
   do_exit (rc);
 }
 
@@ -1057,8 +1079,7 @@ events_terminate (void)
 
 #define pid_offset (unsigned)(((_pinfo *)NULL)->pid)
 extern "C" {
-static void __stdcall
-reset_signal_arrived () __attribute__ ((unused));
+static void __stdcall reset_signal_arrived () __attribute__ ((unused));
 static void __stdcall
 reset_signal_arrived ()
 {
@@ -1077,6 +1098,8 @@ __asm__ volatile ("
 
 _sigreturn:
        addl    $4,%%esp
+       movl    %%esp,%%ebp
+       addl    $36,%%ebp
        call    _set_process_mask@4
        popl    %%eax           # saved errno
        testl   %%eax,%%eax     # Is it < 0
@@ -1089,12 +1112,14 @@ _sigreturn:
        popl    %%edx
        popl    %%edi
        popl    %%esi
+       popl    %%ebp
        popf
        ret
 
 _sigdelayed:
        pushl   %2      # original return address
        pushf
+       pushl   %%ebp
        pushl   %%esi
        pushl   %%edi
        pushl   %%edx
@@ -1111,10 +1136,8 @@ _sigdelayed:
 
        cmpl    $0,_pending_signals
        je      2f
-___sigfirst:
        pushl   $0
        call    _sig_dispatch_pending@4
-___siglast:
 
 2:     jmp     *%5