Welcome to mirror list, hosted at ThFree Co, Russian Federation.

cygwin.com/git/newlib-cygwin.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristopher Faylor <me@cgf.cx>2000-05-20 09:52:33 +0400
committerChristopher Faylor <me@cgf.cx>2000-05-20 09:52:33 +0400
commit6cb613a4287cb3e2feb03999d4090c95034f35d3 (patch)
treefe17193ba3399edf8692722bf483f3a6a03800fc /winsup/cygwin
parenta4bc548973f3e42e9ebb9d41a55617e4c4b77e07 (diff)
* 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.
Diffstat (limited to 'winsup/cygwin')
-rw-r--r--winsup/cygwin/ChangeLog9
-rw-r--r--winsup/cygwin/exceptions.cc95
2 files changed, 67 insertions, 37 deletions
diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog
index 59e7b905a..f471f5b66 100644
--- a/winsup/cygwin/ChangeLog
+++ b/winsup/cygwin/ChangeLog
@@ -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>
* syscalls.cc (setmode): change mode of any matching FILE* also.
diff --git a/winsup/cygwin/exceptions.cc b/winsup/cygwin/exceptions.cc
index b9e58a209..5ebf8de36 100644
--- a/winsup/cygwin/exceptions.cc
+++ b/winsup/cygwin/exceptions.cc
@@ -553,7 +553,7 @@ extern DWORD exec_exit; // Possible exit value for exec
extern int pending_signals;
int
-interruptible (DWORD pc)
+interruptible (DWORD pc, int testvalid = 0)
{
int res;
if ((pc >= (DWORD) &__sigfirst) && (pc <= (DWORD) &__siglast))
@@ -568,7 +568,14 @@ interruptible (DWORD pc)
char *checkdir = (char *) alloca (windows_system_directory_length + 4);
memset (checkdir, 0, sizeof (checkdir));
# 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;
else if (h == cygwin_hmodule)
res = 0;
@@ -654,6 +661,8 @@ set_sig_errno (int e)
debug_printf ("errno %d", e);
}
+#define SUSPEND_TRIES 10000
+
static int
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;
DWORD ebp;
int res;
- int locked;
+ int using_mainthread_frame;
- if (!mainthread.lock)
- locked = 0;
- else
- {
- mainthread.lock->acquire ();
- locked = 1;
- }
+ mainthread.lock->acquire ();
if (mainthread.frame)
- ebp = mainthread.frame;
+ {
+ ebp = mainthread.frame;
+ using_mainthread_frame = 1;
+ }
else
{
- if (locked)
- {
- mainthread.lock->release ();
- locked = 0;
- }
+ int i;
+ using_mainthread_frame = 0;
+ mainthread.lock->release ();
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
- we need those (hack alert). If the thread-to-be-suspended has either of
- these mutos, enter a busy loop until it is released. If the thread is
- already suspended (which should never occur) then just queue the signal. */
- for (;;)
+ 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++)
{
sigproc_printf ("suspending mainthread");
res = SuspendThread (hth);
@@ -697,38 +706,51 @@ call_handler (int sig, struct sigaction& siga, void *handler)
/* FIXME: Make multi-thread aware */
for (m = muto_start.next; m != NULL; m = m->next)
if (m->unstable () || m->owner () == mainthread.id)
- goto keep_looping;
+ goto owns_muto;
+ mainthread.lock->acquire ();
if (mainthread.frame)
{
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;
+ }
+
+ if (interruptible (cx.Eip, 1))
+ break;
- break;
+ sigproc_printf ("suspended thread in a strange state pc %p, sp %p",
+ cx.Eip, cx.Esp);
+ goto resume_thread;
- keep_looping:
+ owns_muto:
sigproc_printf ("suspended thread owns a muto (%s)", m->name);
+
if (res)
- goto set_pending;
+ goto set_pending;
+ resume_thread:
ResumeThread (hth);
Sleep (0);
}
- sigproc_printf ("SuspendThread returned %d", res);
+ if (i >= SUSPEND_TRIES)
+ goto set_pending;
- cx.ContextFlags = CONTEXT_CONTROL | CONTEXT_INTEGER;
- if (!GetThreadContext (hth, &cx))
- {
- system_printf ("couldn't get context of main thread, %E");
- goto out;
- }
+ sigproc_printf ("SuspendThread returned %d", res);
ebp = cx.Ebp;
}
-ebp_set:
- if (hExeced != NULL || (!mainthread.frame && interruptible (cx.Eip)))
+next:
+ if (hExeced != NULL || (!using_mainthread_frame && interruptible (cx.Eip)))
interrupt_now (&cx, sig, siga, handler);
else if (!interrupt_on_return (ebp, sig, siga, handler))
{
@@ -755,8 +777,7 @@ out:
sigproc_printf ("ResumeThread returned %d", res);
}
- if (locked)
- mainthread.lock->release ();
+ mainthread.lock->release ();
sigproc_printf ("returning %d", interrupted);
return interrupted;