* exceptions.cc (interruptible): Make a little more structured.
(call_handler): Allow signals to be sent even if signalled thread is stopped. Change order of signal_arrived arming/waiting threads clearing to eliminate a race. (reset_signal_arrived): New helper function. * malloc.cc (malloc_init): Use mutos so that signal handler can keep track of who owns the lock. (__malloc_lock): Ditto. (__malloc_unlock): Ditto. * sync.h (new_muto): Actually use a muto for the "buffer". * Makefile.in: Fix a dependency.
This commit is contained in:
@ -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;
|
||||
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");
|
||||
|
||||
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)
|
||||
|
Reference in New Issue
Block a user