diff options
Diffstat (limited to 'winsup/cygwin/exceptions.cc')
-rw-r--r-- | winsup/cygwin/exceptions.cc | 72 |
1 files changed, 47 insertions, 25 deletions
diff --git a/winsup/cygwin/exceptions.cc b/winsup/cygwin/exceptions.cc index cc34e8d74..4162ebd6b 100644 --- a/winsup/cygwin/exceptions.cc +++ b/winsup/cygwin/exceptions.cc @@ -44,7 +44,6 @@ extern NO_COPY DWORD dwExeced; int NO_COPY sigExeced; static BOOL WINAPI ctrl_c_handler (DWORD); -static void signal_exit (int) __attribute__ ((noreturn)); char windows_system_directory[1024]; static size_t windows_system_directory_length; @@ -184,7 +183,7 @@ exception (EXCEPTION_RECORD *e, CONTEXT *in) if (exception_name) small_printf ("Exception: %s at eip=%08x\r\n", exception_name, in->Eip); else - small_printf ("Exception %d at eip=%08x\r\n", e->ExceptionCode, in->Eip); + small_printf ("Signal %d at eip=%08x\r\n", e->ExceptionCode, in->Eip); small_printf ("eax=%08x ebx=%08x ecx=%08x edx=%08x esi=%08x edi=%08x\r\n", in->Eax, in->Ebx, in->Ecx, in->Edx, in->Esi, in->Edi); small_printf ("ebp=%08x esp=%08x program=%s, pid %u, thread %s\r\n", @@ -454,7 +453,7 @@ _cygtls::handle_exceptions (EXCEPTION_RECORD *e, exception_list *frame, CONTEXT if (exit_already || e->ExceptionFlags) return 1; - siginfo_t si; + siginfo_t si = {0}; si.si_code = SI_KERNEL; /* Coerce win32 value to posix value. */ switch (e->ExceptionCode) @@ -579,12 +578,15 @@ _cygtls::handle_exceptions (EXCEPTION_RECORD *e, exception_list *frame, CONTEXT break; } - if (!me.fault_guarded () - && (!cygwin_finished_initializing - || &me == _sig_tls - || (void *) global_sigs[si.si_signo].sa_handler == (void *) SIG_DFL - || (void *) global_sigs[si.si_signo].sa_handler == (void *) SIG_IGN - || (void *) global_sigs[si.si_signo].sa_handler == (void *) SIG_ERR)) + if (me.fault_guarded ()) + me.return_from_fault (); + + me.copy_context (in); + if (!cygwin_finished_initializing + || &me == _sig_tls + || (void *) global_sigs[si.si_signo].sa_handler == (void *) SIG_DFL + || (void *) global_sigs[si.si_signo].sa_handler == (void *) SIG_IGN + || (void *) global_sigs[si.si_signo].sa_handler == (void *) SIG_ERR) { /* Print the exception to the console */ if (!myself->cygstarted) @@ -613,7 +615,7 @@ _cygtls::handle_exceptions (EXCEPTION_RECORD *e, exception_list *frame, CONTEXT } if (e->ExceptionCode == STATUS_ACCESS_VIOLATION) - { + { int error_code = 0; if (si.si_code == SEGV_ACCERR) /* Address present */ error_code |= 1; @@ -628,12 +630,9 @@ _cygtls::handle_exceptions (EXCEPTION_RECORD *e, exception_list *frame, CONTEXT ? 0 : 4) | (e->ExceptionInformation[0] << 1)); } - signal_exit (0x80 | si.si_signo); // Flag signal + core dump + me.signal_exit (0x80 | si.si_signo); // Flag signal + core dump } - if (me.fault_guarded ()) - me.return_from_fault (); - si.si_addr = (void *) in->Eip; si.si_errno = si.si_pid = si.si_uid = 0; me.incyg++; @@ -755,6 +754,15 @@ _cygtls::interrupt_setup (int sig, void *handler, struct sigaction& siga) this->sig = sig; // Should always be last thing set to avoid a race + if (!event) + threadkill = false; + else + { + HANDLE h = event; + event = NULL; + SetEvent (h); + } + /* Clear any waiting threads prior to dispatching to handler function */ int res = SetEvent (signal_arrived); // For an EINTR case proc_subproc (PROC_CLEARWAIT, 1); @@ -841,12 +849,6 @@ setup_handler (int sig, void *handler, struct sigaction& siga, _cygtls *tls) } out: - if (interrupted && tls->event) - { - HANDLE h = tls->event; - tls->event = NULL; - SetEvent (h); - } sigproc_printf ("signal %d %sdelivered", sig, interrupted ? "" : "not "); return interrupted; } @@ -1209,19 +1211,18 @@ exit_sig: CONTEXT c; c.ContextFlags = CONTEXT_FULL; GetThreadContext (hMainThread, &c); - if (!try_to_debug ()) - stackdump (c.Ebp, 1, 1); + tls->copy_context (&c); si.si_signo |= 0x80; } sigproc_printf ("signal %d, about to call do_exit", si.si_signo); - signal_exit (si.si_signo); /* never returns */ + tls->signal_exit (si.si_signo); /* never returns */ } /* Cover function to `do_exit' to handle exiting even in presence of more exceptions. We used to call exit, but a SIGSEGV shouldn't cause atexit routines to run. */ -static void -signal_exit (int rc) +void +_cygtls::signal_exit (int rc) { if (hExeced) { @@ -1229,6 +1230,10 @@ signal_exit (int rc) TerminateProcess (hExeced, sigExeced = rc); } + signal_debugger (rc & 0x7f); + if ((rc & 0x80) && !try_to_debug ()) + stackdump (thread_context.ebp, 1, 1); + lock_process until_exit (true); if (hExeced || exit_state) myself.exit (rc); @@ -1331,3 +1336,20 @@ reset_signal_arrived () if (_my_tls.stackptr > _my_tls.stack) debug_printf ("stackptr[-1] %p", _my_tls.stackptr[-1]); } + +void +_cygtls::copy_context (CONTEXT *c) +{ + memcpy (&thread_context, c, (&thread_context._internal - (unsigned char *) &thread_context)); +} + +void +_cygtls::signal_debugger (int sig) +{ + if (being_debugged ()) + { + char sigmsg[2 * sizeof (_CYGWIN_SIGNAL_STRING " ffffffff ffffffff")]; + __small_sprintf (sigmsg, _CYGWIN_SIGNAL_STRING " %d %p %p", sig, thread_id, &thread_context); + OutputDebugString (sigmsg); + } +} |