* exceptions.cc (interruptible): Add an argument to control whether function
just checks for validity. Flag module handle == 0 as noninterrupible. (call_handler): Always acquire and release ebp lock. Loop for only a fixed amount of time attempting to grab mutos and find an interruptible PC.
This commit is contained in:
parent
a4bc548973
commit
6cb613a428
|
@ -1,3 +1,12 @@
|
||||||
|
Sat May 20 01:34:57 2000 Christopher Faylor <cgf@cygnus.com>
|
||||||
|
|
||||||
|
* exceptions.cc (interruptible): Add an argument to control whether
|
||||||
|
function just checks for validity. Flag module handle == 0 as
|
||||||
|
noninterrupible.
|
||||||
|
(call_handler): Always acquire and release ebp lock. Loop for only a
|
||||||
|
fixed amount of time attempting to grab mutos and find an interruptible
|
||||||
|
PC.
|
||||||
|
|
||||||
2000-05-19 DJ Delorie <dj@cygnus.com>
|
2000-05-19 DJ Delorie <dj@cygnus.com>
|
||||||
|
|
||||||
* syscalls.cc (setmode): change mode of any matching FILE* also.
|
* syscalls.cc (setmode): change mode of any matching FILE* also.
|
||||||
|
|
|
@ -553,7 +553,7 @@ extern DWORD exec_exit; // Possible exit value for exec
|
||||||
extern int pending_signals;
|
extern int pending_signals;
|
||||||
|
|
||||||
int
|
int
|
||||||
interruptible (DWORD pc)
|
interruptible (DWORD pc, int testvalid = 0)
|
||||||
{
|
{
|
||||||
int res;
|
int res;
|
||||||
if ((pc >= (DWORD) &__sigfirst) && (pc <= (DWORD) &__siglast))
|
if ((pc >= (DWORD) &__sigfirst) && (pc <= (DWORD) &__siglast))
|
||||||
|
@ -568,7 +568,14 @@ interruptible (DWORD pc)
|
||||||
char *checkdir = (char *) alloca (windows_system_directory_length + 4);
|
char *checkdir = (char *) alloca (windows_system_directory_length + 4);
|
||||||
memset (checkdir, 0, sizeof (checkdir));
|
memset (checkdir, 0, sizeof (checkdir));
|
||||||
# define h ((HMODULE) m.AllocationBase)
|
# define h ((HMODULE) m.AllocationBase)
|
||||||
if (h == user_data->hmodule)
|
/* 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;
|
res = 1;
|
||||||
else if (h == cygwin_hmodule)
|
else if (h == cygwin_hmodule)
|
||||||
res = 0;
|
res = 0;
|
||||||
|
@ -654,6 +661,8 @@ set_sig_errno (int e)
|
||||||
debug_printf ("errno %d", e);
|
debug_printf ("errno %d", e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define SUSPEND_TRIES 10000
|
||||||
|
|
||||||
static int
|
static int
|
||||||
call_handler (int sig, struct sigaction& siga, void *handler)
|
call_handler (int sig, struct sigaction& siga, void *handler)
|
||||||
{
|
{
|
||||||
|
@ -662,33 +671,33 @@ call_handler (int sig, struct sigaction& siga, void *handler)
|
||||||
HANDLE hth = NULL;
|
HANDLE hth = NULL;
|
||||||
DWORD ebp;
|
DWORD ebp;
|
||||||
int res;
|
int res;
|
||||||
int locked;
|
int using_mainthread_frame;
|
||||||
|
|
||||||
if (!mainthread.lock)
|
mainthread.lock->acquire ();
|
||||||
locked = 0;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
mainthread.lock->acquire ();
|
|
||||||
locked = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mainthread.frame)
|
if (mainthread.frame)
|
||||||
ebp = mainthread.frame;
|
{
|
||||||
|
ebp = mainthread.frame;
|
||||||
|
using_mainthread_frame = 1;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (locked)
|
int i;
|
||||||
{
|
using_mainthread_frame = 0;
|
||||||
mainthread.lock->release ();
|
mainthread.lock->release ();
|
||||||
locked = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
hth = myself->getthread2signal ();
|
hth = myself->getthread2signal ();
|
||||||
/* Suspend the thread which will receive the signal. But first ensure that
|
/* 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
|
this thread doesn't have any mutos. (FIXME: Someday we should just grab
|
||||||
we need those (hack alert). If the thread-to-be-suspended has either of
|
all of the mutos rather than checking for them)
|
||||||
these mutos, enter a busy loop until it is released. If the thread is
|
For Windows 95, we also have to ensure that the addresses returned by GetThreadContext
|
||||||
already suspended (which should never occur) then just queue the signal. */
|
are valid.
|
||||||
for (;;)
|
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++)
|
||||||
{
|
{
|
||||||
sigproc_printf ("suspending mainthread");
|
sigproc_printf ("suspending mainthread");
|
||||||
res = SuspendThread (hth);
|
res = SuspendThread (hth);
|
||||||
|
@ -697,38 +706,51 @@ call_handler (int sig, struct sigaction& siga, void *handler)
|
||||||
/* FIXME: Make multi-thread aware */
|
/* FIXME: Make multi-thread aware */
|
||||||
for (m = muto_start.next; m != NULL; m = m->next)
|
for (m = muto_start.next; m != NULL; m = m->next)
|
||||||
if (m->unstable () || m->owner () == mainthread.id)
|
if (m->unstable () || m->owner () == mainthread.id)
|
||||||
goto keep_looping;
|
goto owns_muto;
|
||||||
|
|
||||||
|
mainthread.lock->acquire ();
|
||||||
if (mainthread.frame)
|
if (mainthread.frame)
|
||||||
{
|
{
|
||||||
ebp = mainthread.frame; /* try to avoid a race */
|
ebp = mainthread.frame; /* try to avoid a race */
|
||||||
goto ebp_set;
|
using_mainthread_frame = 1;
|
||||||
|
goto next;
|
||||||
|
}
|
||||||
|
mainthread.lock->release ();
|
||||||
|
|
||||||
|
cx.ContextFlags = CONTEXT_CONTROL | CONTEXT_INTEGER;
|
||||||
|
if (!GetThreadContext (hth, &cx))
|
||||||
|
{
|
||||||
|
system_printf ("couldn't get context of main thread, %E");
|
||||||
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
if (interruptible (cx.Eip, 1))
|
||||||
|
break;
|
||||||
|
|
||||||
keep_looping:
|
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);
|
sigproc_printf ("suspended thread owns a muto (%s)", m->name);
|
||||||
|
|
||||||
if (res)
|
if (res)
|
||||||
goto set_pending;
|
goto set_pending;
|
||||||
|
|
||||||
|
resume_thread:
|
||||||
ResumeThread (hth);
|
ResumeThread (hth);
|
||||||
Sleep (0);
|
Sleep (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
sigproc_printf ("SuspendThread returned %d", res);
|
if (i >= SUSPEND_TRIES)
|
||||||
|
goto set_pending;
|
||||||
|
|
||||||
cx.ContextFlags = CONTEXT_CONTROL | CONTEXT_INTEGER;
|
sigproc_printf ("SuspendThread returned %d", res);
|
||||||
if (!GetThreadContext (hth, &cx))
|
|
||||||
{
|
|
||||||
system_printf ("couldn't get context of main thread, %E");
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
ebp = cx.Ebp;
|
ebp = cx.Ebp;
|
||||||
}
|
}
|
||||||
|
|
||||||
ebp_set:
|
next:
|
||||||
if (hExeced != NULL || (!mainthread.frame && interruptible (cx.Eip)))
|
if (hExeced != NULL || (!using_mainthread_frame && interruptible (cx.Eip)))
|
||||||
interrupt_now (&cx, sig, siga, handler);
|
interrupt_now (&cx, sig, siga, handler);
|
||||||
else if (!interrupt_on_return (ebp, sig, siga, handler))
|
else if (!interrupt_on_return (ebp, sig, siga, handler))
|
||||||
{
|
{
|
||||||
|
@ -755,8 +777,7 @@ out:
|
||||||
sigproc_printf ("ResumeThread returned %d", res);
|
sigproc_printf ("ResumeThread returned %d", res);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (locked)
|
mainthread.lock->release ();
|
||||||
mainthread.lock->release ();
|
|
||||||
|
|
||||||
sigproc_printf ("returning %d", interrupted);
|
sigproc_printf ("returning %d", interrupted);
|
||||||
return interrupted;
|
return interrupted;
|
||||||
|
|
Loading…
Reference in New Issue