diff options
author | Christopher Faylor <me@cgf.cx> | 2004-02-12 03:01:58 +0000 |
---|---|---|
committer | Christopher Faylor <me@cgf.cx> | 2004-02-12 03:01:58 +0000 |
commit | e431827c7cab81292e8cd4ec9d3a4a60b35a42f2 (patch) | |
tree | 1b9056071ae2ab09f0d3474904a4c5f71599128d /winsup/cygwin/exceptions.cc | |
parent | 2bc01fb1f5d3166c4960c5f9a1ff617f0f46a60d (diff) | |
download | cygnal-e431827c7cab81292e8cd4ec9d3a4a60b35a42f2.tar.gz cygnal-e431827c7cab81292e8cd4ec9d3a4a60b35a42f2.tar.bz2 cygnal-e431827c7cab81292e8cd4ec9d3a4a60b35a42f2.zip |
Rename _threadinfo to _cygtls, throughout.
* cygtls.h (_cygtls::call_signal_handler): Rename from call_signal_handler_now.
(_cygtls::push): Make second argument mandatory.
(_cygtls::fixup_after_fork): Declare new function.
(_cygtls::lock): Ditto.
* cygtls.cc (_cygtls::fixup_after_fork): Define new function.
* dcrt0.cc (cygwin_finished_initializing): Define as bool.
(alloc_stack): Use _tlstop rather than arbitrary variable in probably vain
attempt to avoid strange fork problem on CTRL-C.
(dll_crt0_0): Remove obsolete winpids::init call.
* dll_init.cc (dll_dllcrt0): Detect forkee condition as equivalent to
initializing.
* winsup.h (cygwin_finished_initializing): Declare as bool.
* exceptions.cc (handle_exceptions): Rely on cygwin_finished_initializing to
determine how to handle exception during process startup.
(_cygtls::call_signal_handler): Rename from call_signal_handler_now.
(_cygtls::interrupt_now): Fill in second argument to push.
(signal_fixup_after_fork): Eliminate.
(setup_handler): Initialize locked to avoid potential inappropriate unlock.
Resume thread if it has acquired the stack lock.
(ctrl_c_handler): Just exit if ctrl-c is hit before cygiwn has finished
initializing.
* fork.cc (sync_with_child): Don't call abort since it can cause exit
deadlocks.
(sync_with_child): Change debugging output slightly.
(fork_child): Set cygwin_finished_initializing here. Call _cygtls fork fixup
and explicitly call sigproc_init.
(fork_parent): Release malloc lock on fork failure.
(vfork): Call signal handler via _my_tls.
* sigproc.cc (sig_send): Ditto.
* syscalls.cc (readv): Ditto.
* termios.cc (tcsetattr): Ditto.
* wait.cc (wait4): Ditto.
* signal.cc (nanosleep): Ditto.
(abort): Ditto.
(kill_pgrp): Avoid killing self if exiting.
* sync.cc (muto::acquire): Remove (temporarily?) ill-advised exiting_thread
check.
* gendef (_sigfe): Be more agressive in protecting stack pointer from other
access by signal thread.
(_cygtls::locked): Define new function.
(_sigbe): Ditto.
(_cygtls::pop): Protect edx.
(_cygtls::lock): Use guaranteed method to set eax to 1.
(longjmp): Aggressively protect signal stack.
* miscfuncs.cc (low_priority_sleep): Reduce "sleep time" for secs == 0.
* pinfo.cc (winpids::set): Counterintuitively use malloc's lock to protect
simultaneous access to the pids list since there are pathological conditions
which can cause malloc to call winpid.
(winpids::init): Eliminate.
* pinfo.h (winpids::cs): Eliminate declaration.
* pinfo.h (winpids::init): Eliminate definition.
Diffstat (limited to 'winsup/cygwin/exceptions.cc')
-rw-r--r-- | winsup/cygwin/exceptions.cc | 106 |
1 files changed, 46 insertions, 60 deletions
diff --git a/winsup/cygwin/exceptions.cc b/winsup/cygwin/exceptions.cc index 03df67f10..490756544 100644 --- a/winsup/cygwin/exceptions.cc +++ b/winsup/cygwin/exceptions.cc @@ -519,7 +519,7 @@ handle_exceptions (EXCEPTION_RECORD *e0, void *frame, CONTEXT *in0, void *) break; } - if (!myself->progname[0] + if (!cygwin_finished_initializing || GetCurrentThreadId () == sigtid || (void *) global_sigs[si.si_signo].sa_handler == (void *) SIG_DFL || (void *) global_sigs[si.si_signo].sa_handler == (void *) SIG_IGN @@ -692,10 +692,10 @@ interruptible (DWORD pc) return res; } void __stdcall -_threadinfo::interrupt_setup (int sig, void *handler, +_cygtls::interrupt_setup (int sig, void *handler, struct sigaction& siga) { - push ((__stack_t) sigdelayed); + push ((__stack_t) sigdelayed, false); oldmask = myself->getsigmask (); newmask = oldmask | siga.sa_mask | SIGTOMASK (sig); sa_flags = siga.sa_flags; @@ -717,28 +717,16 @@ _threadinfo::interrupt_setup (int sig, void *handler, } bool -_threadinfo::interrupt_now (CONTEXT *ctx, int sig, void *handler, +_cygtls::interrupt_now (CONTEXT *ctx, int sig, void *handler, struct sigaction& siga) { - push ((__stack_t) ctx->Eip); + push ((__stack_t) ctx->Eip, false); interrupt_setup (sig, handler, siga); ctx->Eip = pop (); SetThreadContext (*this, ctx); /* Restart the thread in a new location */ return 1; } -void __stdcall -signal_fixup_after_fork () -{ - if (_my_tls.sig) - { - _my_tls.sig = 0; - _my_tls.stackptr = _my_tls.stack + 1; // FIXME? - set_signal_mask (_my_tls.oldmask); - } - sigproc_init (); -} - extern "C" void __stdcall set_sig_errno (int e) { @@ -747,13 +735,14 @@ set_sig_errno (int e) // sigproc_printf ("errno %d", e); } -static int setup_handler (int, void *, struct sigaction&, _threadinfo *tls) +static int setup_handler (int, void *, struct sigaction&, _cygtls *tls) __attribute__((regparm(3))); static int -setup_handler (int sig, void *handler, struct sigaction& siga, _threadinfo *tls) +setup_handler (int sig, void *handler, struct sigaction& siga, _cygtls *tls) { CONTEXT cx; bool interrupted = false; + bool locked = false; if (tls->sig) { @@ -762,12 +751,11 @@ setup_handler (int sig, void *handler, struct sigaction& siga, _threadinfo *tls) goto out; } - int locked; for (int i = 0; i < CALL_HANDLER_RETRY; i++) { - locked = tls->lock (); - __stack_t *retaddr_on_stack = tls->stackptr - 1; - if (retaddr_on_stack >= tls->stack) + tls->lock (); + locked = true; + if (tls->stackptr > tls->stack) { tls->reset_exception (); tls->interrupt_setup (sig, handler, siga); @@ -776,14 +764,14 @@ setup_handler (int sig, void *handler, struct sigaction& siga, _threadinfo *tls) break; } + tls->unlock (); + locked = false; DWORD res; HANDLE hth = (HANDLE) *tls; - /* Suspend the thread which will receive the signal. But first ensure that - 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. + /* Suspend the thread which will receive the signal. + 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? @@ -799,31 +787,25 @@ setup_handler (int sig, void *handler, struct sigaction& siga, _threadinfo *tls) sigproc_printf ("suspending mainthread PC %p", cx.Eip); #endif res = SuspendThread (hth); - /* Just release the lock now since we hav suspended the main thread and it - definitely can't be grabbing it now. This will have to change, of course, - if/when we can send signals to other than the main thread. */ - /* Just set pending if thread is already suspended */ if (res) { (void) ResumeThread (hth); break; } - - // FIXME - add check for reentering of DLL here - - cx.ContextFlags = CONTEXT_CONTROL | CONTEXT_INTEGER; - if (!GetThreadContext (hth, &cx)) - system_printf ("couldn't get context of main thread, %E"); - else if (interruptible (cx.Eip)) - interrupted = tls->interrupt_now (&cx, sig, handler, siga); + if (!tls->locked ()) + { + cx.ContextFlags = CONTEXT_CONTROL | CONTEXT_INTEGER; + if (!GetThreadContext (hth, &cx)) + system_printf ("couldn't get context of main thread, %E"); + else if (interruptible (cx.Eip)) + interrupted = tls->interrupt_now (&cx, sig, handler, siga); + } res = ResumeThread (hth); if (interrupted) break; - tls->unlock (); - locked = false; sigproc_printf ("couldn't interrupt. trying again."); low_priority_sleep (0); } @@ -845,6 +827,10 @@ static BOOL WINAPI ctrl_c_handler (DWORD type) { static bool saw_close; + + if (!cygwin_finished_initializing) + ExitProcess (STATUS_CONTROL_C_EXIT); + _my_tls.remove (INFINITE); /* Return FALSE to prevent an "End task" dialog box from appearing @@ -977,7 +963,7 @@ sigpacket::process () /* nothing to do */; else if (tls && sigismember (&tls->sigwait_mask, si.si_signo)) insigwait_mask = true; - else if (!tls && (tls = _threadinfo::find_tls (si.si_signo))) + else if (!tls && (tls = _cygtls::find_tls (si.si_signo))) insigwait_mask = true; else if (!(masked = sigismember (mask, si.si_signo)) && tls) masked = sigismember (&tls->sigmask, si.si_signo); @@ -1153,36 +1139,36 @@ events_terminate (void) exit_already = 1; } -extern "C" { -int __stdcall -call_signal_handler_now () +int +_cygtls::call_signal_handler () { - int sa_flags = 0; - while (_my_tls.sig && _my_tls.stackptr > _my_tls.stack) + int this_sa_flags = 0; + /* Call signal handler. No need to set stacklock since sig effectively + implies that. */ + while (sig) { - sa_flags = _my_tls.sa_flags; - int sig = _my_tls.sig; - void (*sigfunc) (int) = _my_tls.func; + this_sa_flags = sa_flags; + int thissig = sig; + void (*sigfunc) (int) = func; - (void) _my_tls.pop (); + (void) pop (); reset_signal_arrived (); - sigset_t oldmask = _my_tls.oldmask; - int this_errno = _my_tls.saved_errno; - set_process_mask (_my_tls.newmask); - _my_tls.sig = 0; - sigfunc (sig); + sigset_t oldmask = oldmask; + int this_errno = saved_errno; + set_process_mask (newmask); + sig = 0; + sigfunc (thissig); set_process_mask (oldmask); if (this_errno >= 0) set_errno (this_errno); } - return sa_flags & SA_RESTART; + return this_sa_flags & SA_RESTART; } -void __stdcall +extern "C" void __stdcall reset_signal_arrived () { (void) ResetEvent (signal_arrived); sigproc_printf ("reset signal_arrived"); } -} |