summaryrefslogtreecommitdiffstats
path: root/winsup/cygwin/exceptions.cc
diff options
context:
space:
mode:
Diffstat (limited to 'winsup/cygwin/exceptions.cc')
-rw-r--r--winsup/cygwin/exceptions.cc75
1 files changed, 45 insertions, 30 deletions
diff --git a/winsup/cygwin/exceptions.cc b/winsup/cygwin/exceptions.cc
index 3213aa972..1cfe1e701 100644
--- a/winsup/cygwin/exceptions.cc
+++ b/winsup/cygwin/exceptions.cc
@@ -18,6 +18,7 @@ details. */
#define DECLSPEC_IMPORT
#include <imagehlp.h>
#include "autoload.h"
+#include "sync.h"
char debugger_command[2 * MAX_PATH + 20];
@@ -557,7 +558,7 @@ handle_exceptions (EXCEPTION_RECORD *e, void *, CONTEXT *in, void *)
bp -= 2;
break;
}
-
+
in->Ebp = (DWORD) bp;
sigsave.cx = in;
sig_send (NULL, sig); // Signal myself
@@ -621,21 +622,28 @@ interruptible (DWORD pc)
return ((pc >= (DWORD) &__sigfirst) && (pc <= (DWORD) &__siglast)) ||
!(pchigh == 0xb0000000 || pchigh == 0x70000000 || pchigh == 0x60000000);
#else
+ int res = 1;
if ((pc >= (DWORD) &__sigfirst) && (pc <= (DWORD) &__siglast))
- return 1;
-
- MEMORY_BASIC_INFORMATION m;
- memset (&m, 0, sizeof m);
- if (!VirtualQuery ((LPCVOID) pc, &m, sizeof m))
- sigproc_printf ("couldn't get memory info, %E");
+ 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);
+# define h ((HMODULE) m.AllocationBase)
+ if (h == cygwin_hmodule)
+ res = 0;
+ else if (!GetModuleFileName (h, checkdir, windows_system_directory_length))
+ res = 0;
+ else
+ res = !strncasematch (windows_system_directory, checkdir,
+ windows_system_directory_length);
+ }
-# define h ((HMODULE) m.AllocationBase)
- if (h == cygwin_hmodule)
- return 0;
- char *checkdir = (char *) alloca (windows_system_directory_length);
- if (!GetModuleFileName (h, checkdir, windows_system_directory_length))
- return 0;
- return !strncasematch (windows_system_directory, checkdir, windows_system_directory_length);
+ return res;
# undef h
#endif
}
@@ -727,7 +735,6 @@ call_handler (int sig, struct sigaction& siga, void *handler)
we have to do that since sometimes they don't return - and if
this thread doesn't return, you won't ever get another exception. */
- sigproc_printf ("Suspending %p (mainthread)", myself->getthread2signal());
HANDLE hth = myself->getthread2signal ();
/* Suspend the thread which will receive the signal. But first ensure that
this thread doesn't have the sync_proc_subproc and mask_sync mutos, since
@@ -736,11 +743,9 @@ call_handler (int sig, struct sigaction& siga, void *handler)
already suspended (which should never occur) then just queue the signal. */
for (;;)
{
+ sigproc_printf ("suspending mainthread");
res = SuspendThread (hth);
- if (res)
- goto set_pending;
-
/* FIXME: Make multi-thread aware */
for (muto *m = muto_start.next; m != NULL; m = m->next)
if (m->unstable () || m->owner () == maintid)
@@ -749,10 +754,14 @@ call_handler (int sig, struct sigaction& siga, void *handler)
break;
keep_looping:
+ sigproc_printf ("suspended thread owns a muto");
+ if (res)
+ goto set_pending;
+
ResumeThread (hth);
Sleep (0);
}
-
+
sigproc_printf ("suspend said %d, %E", res);
if (sigsave.cx)
@@ -783,12 +792,6 @@ call_handler (int sig, struct sigaction& siga, void *handler)
interrupted = 0;
}
- if (interrupted)
- {
- /* Clear any waiting threads prior to dispatching to handler function */
- proc_subproc(PROC_CLEARWAIT, 1);
- }
-
(void) ResumeThread (hth);
if (interrupted)
@@ -796,6 +799,8 @@ call_handler (int sig, struct sigaction& siga, void *handler)
/* Apparently we have to set signal_arrived after resuming the thread or it
is possible that the event will be ignored. */
(void) SetEvent (signal_arrived); // For an EINTR case
+ /* Clear any waiting threads prior to dispatching to handler function */
+ proc_subproc(PROC_CLEARWAIT, 1);
}
sigproc_printf ("armed signal_arrived %p, res %d", signal_arrived, res);
@@ -1068,6 +1073,15 @@ 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 ()
+{
+ (void) ResetEvent (signal_arrived);
+ sigproc_printf ("reset signal_arrived");
+}
+
void unused_sig_wrapper()
{
/* Signal cleanup stuff. Cleans up stack (too bad that we didn't
@@ -1076,7 +1090,6 @@ void unused_sig_wrapper()
and returns to orignal caller. */
__asm__ volatile ("
.text
-___sigfirst:
.globl __raise
__raise:
pushl %%ebp
@@ -1120,19 +1133,21 @@ _sigdelayed:
pushl %3 # oldmask
pushl %4 # signal argument
pushl $_sigreturn
- movl $0,%0
- pushl _signal_arrived # Everybody waiting for this should
- call _ResetEvent@4 # have woken up by now.
+ call _reset_signal_arrived@0
+# pushl _signal_arrived # Everybody waiting for this should
+# call _ResetEvent@4 # have woken up by now.
+ movl $0,%0
cmpl $0,_pending_signals
je 2f
+___sigfirst:
pushl $0
call _sig_dispatch_pending@4
+___siglast:
2: jmp *%5
-___siglast:
" : "=m" (sigsave.sig) : "m" (&_impure_ptr->_errno),
"g" (sigsave.retaddr), "g" (sigsave.oldmask), "g" (sigsave.sig),
"g" (sigsave.func), "o" (pid_offset), "g" (sigsave.saved_errno)