mirror of
git://sourceware.org/git/newlib-cygwin.git
synced 2025-01-19 21:09:22 +08:00
* cygtls.h (_cygtls::signal_exit): Delete from class.
* exception.h (cygwin_exception): New class. (cygwin_exception::dumpstack): Declare new function. (cygwin_exception::context): Ditto. (cygwin_exception::dump_exception): Ditto. * exceptions.cc (cygwin_exception::dump_exception): Move into cygwin_exception class. Accommodate new variable names. (cygwin_exception::dumpstack): Ditto stackdump -> dumpstack. (exception::handle): Move andreas processing earlier. Defer signal processing decisions to the signal thread where they belong. Pass exception information to sig_send via new siginfo_t si_cyg field. (ctrl_c_handler): Wait for SIGHUP signal to be processed since it could cause a process exit and we don't want races with thread exit lock. (signal_exit): Move back here from sigproc.cc. Modify arguments and remove from sigpacket class. Decide when to dump core based on signal type. (sigpacket::process): Handle exiting signals in context of threads rather than in the signal thread. Signal debugger on non-Windows signals. Remove setup_signal_exit call. * sigproc.cc (no_signals_available): Remove argument. (signal_exit_code): Delete. (close_my_readsig): Ditto. (_cygtls::signal_exit): Move to exceptions.cc. (sigproc_terminate): Don't attempt to terminate signal thread. (setup_signal_exit): Delete. (exit_thread): Use new si_cyg entry in siginfo_t. (sig_send): Just use empty initializer for si. Accommodate change in no_signals_available argument. (wait_sig): Remove attempt to "go asynchronous" on process exit. Delete __SIGEXIT handling. Don't ever exit. * sigproc.h: Remove __SIGEXIT from signal enum. Renumber. * include/cygwin/signal.h (siginfo_t): Add si_cyg entry.
This commit is contained in:
parent
74f8546d6e
commit
ca77b848e7
File diff suppressed because it is too large
Load Diff
3065
winsup/cygwin/ChangeLog-2012
Normal file
3065
winsup/cygwin/ChangeLog-2012
Normal file
File diff suppressed because it is too large
Load Diff
@ -1,6 +1,6 @@
|
|||||||
/* cygtls.h
|
/* cygtls.h
|
||||||
|
|
||||||
Copyright 2003, 2004, 2005, 2008, 2009, 2010, 2011, 2012 Red Hat, Inc.
|
Copyright 2003, 2004, 2005, 2008, 2009, 2010, 2011, 2012, 2013 Red Hat, Inc.
|
||||||
|
|
||||||
This software is a copyrighted work licensed under the terms of the
|
This software is a copyrighted work licensed under the terms of the
|
||||||
Cygwin license. Please consult the file "CYGWIN_LICENSE" for
|
Cygwin license. Please consult the file "CYGWIN_LICENSE" for
|
||||||
@ -220,7 +220,6 @@ public:
|
|||||||
__attribute__((regparm(3)));
|
__attribute__((regparm(3)));
|
||||||
|
|
||||||
bool inside_kernel (CONTEXT *);
|
bool inside_kernel (CONTEXT *);
|
||||||
void signal_exit (int) __attribute__ ((noreturn, regparm(2)));
|
|
||||||
void copy_context (CONTEXT *) __attribute__ ((regparm(2)));
|
void copy_context (CONTEXT *) __attribute__ ((regparm(2)));
|
||||||
void signal_debugger (int) __attribute__ ((regparm(2)));
|
void signal_debugger (int) __attribute__ ((regparm(2)));
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/* exception.h
|
/* exception.h
|
||||||
|
|
||||||
Copyright 2010, 2011, 2012 Red Hat, Inc.
|
Copyright 2010, 2011, 2012, 2013 Red Hat, Inc.
|
||||||
|
|
||||||
This software is a copyrighted work licensed under the terms of the
|
This software is a copyrighted work licensed under the terms of the
|
||||||
Cygwin license. Please consult the file "CYGWIN_LICENSE" for
|
Cygwin license. Please consult the file "CYGWIN_LICENSE" for
|
||||||
@ -28,10 +28,15 @@ public:
|
|||||||
~exception () __attribute__ ((always_inline)) { _except_list = save; }
|
~exception () __attribute__ ((always_inline)) { _except_list = save; }
|
||||||
};
|
};
|
||||||
|
|
||||||
void stackdump (DWORD, CONTEXT * = NULL, EXCEPTION_RECORD * = NULL);
|
class cygwin_exception
|
||||||
extern void inline
|
|
||||||
stackdump (DWORD n, bool)
|
|
||||||
{
|
{
|
||||||
stackdump (n, (CONTEXT *) 1);
|
DWORD ebp;
|
||||||
}
|
PCONTEXT ctx;
|
||||||
|
EXCEPTION_RECORD *e;
|
||||||
|
void dump_exception ();
|
||||||
|
public:
|
||||||
|
cygwin_exception (DWORD in_ebp, PCONTEXT in_ctx = NULL, EXCEPTION_RECORD *in_e = NULL):
|
||||||
|
ebp (in_ebp), ctx (in_ctx), e (in_e) {}
|
||||||
|
void dumpstack ();
|
||||||
|
PCONTEXT context () const {return ctx;}
|
||||||
|
};
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/* exceptions.cc
|
/* exceptions.cc
|
||||||
|
|
||||||
Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
|
Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
|
||||||
2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 Red Hat, Inc.
|
2007, 2008, 2009, 2010, 2011, 2012, 2013 Red Hat, Inc.
|
||||||
|
|
||||||
This file is part of Cygwin.
|
This file is part of Cygwin.
|
||||||
|
|
||||||
@ -163,8 +163,8 @@ open_stackdumpfile ()
|
|||||||
|
|
||||||
/* Utilities for dumping the stack, etc. */
|
/* Utilities for dumping the stack, etc. */
|
||||||
|
|
||||||
static void
|
void
|
||||||
dump_exception (EXCEPTION_RECORD *e, CONTEXT *in)
|
cygwin_exception::dump_exception ()
|
||||||
{
|
{
|
||||||
const char *exception_name = NULL;
|
const char *exception_name = NULL;
|
||||||
|
|
||||||
@ -181,15 +181,15 @@ dump_exception (EXCEPTION_RECORD *e, CONTEXT *in)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (exception_name)
|
if (exception_name)
|
||||||
small_printf ("Exception: %s at eip=%08x\r\n", exception_name, in->Eip);
|
small_printf ("Exception: %s at eip=%08x\r\n", exception_name, ctx->Eip);
|
||||||
else
|
else
|
||||||
small_printf ("Signal %d at eip=%08x\r\n", e->ExceptionCode, in->Eip);
|
small_printf ("Signal %d at eip=%08x\r\n", e->ExceptionCode, ctx->Eip);
|
||||||
small_printf ("eax=%08x ebx=%08x ecx=%08x edx=%08x esi=%08x edi=%08x\r\n",
|
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);
|
ctx->Eax, ctx->Ebx, ctx->Ecx, ctx->Edx, ctx->Esi, ctx->Edi);
|
||||||
small_printf ("ebp=%08x esp=%08x program=%W, pid %u, thread %s\r\n",
|
small_printf ("ebp=%08x esp=%08x program=%W, pid %u, thread %s\r\n",
|
||||||
in->Ebp, in->Esp, myself->progname, myself->pid, cygthread::name ());
|
ctx->Ebp, ctx->Esp, myself->progname, myself->pid, cygthread::name ());
|
||||||
small_printf ("cs=%04x ds=%04x es=%04x fs=%04x gs=%04x ss=%04x\r\n",
|
small_printf ("cs=%04x ds=%04x es=%04x fs=%04x gs=%04x ss=%04x\r\n",
|
||||||
in->SegCs, in->SegDs, in->SegEs, in->SegFs, in->SegGs, in->SegSs);
|
ctx->SegCs, ctx->SegDs, ctx->SegEs, ctx->SegFs, ctx->SegGs, ctx->SegSs);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* A class for manipulating the stack. */
|
/* A class for manipulating the stack. */
|
||||||
@ -273,7 +273,7 @@ stack_info::walk ()
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
stackdump (DWORD ebp, PCONTEXT in, EXCEPTION_RECORD *e)
|
cygwin_exception::dumpstack ()
|
||||||
{
|
{
|
||||||
static bool already_dumped;
|
static bool already_dumped;
|
||||||
|
|
||||||
@ -283,11 +283,11 @@ stackdump (DWORD ebp, PCONTEXT in, EXCEPTION_RECORD *e)
|
|||||||
open_stackdumpfile ();
|
open_stackdumpfile ();
|
||||||
|
|
||||||
if (e)
|
if (e)
|
||||||
dump_exception (e, in);
|
dump_exception ();
|
||||||
|
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
thestack.init (ebp, 1, !in); /* Initialize from the input CONTEXT */
|
thestack.init (ebp, 1, !ctx); /* Initialize from the input CONTEXT */
|
||||||
small_printf ("Stack trace:\r\nFrame Function Args\r\n");
|
small_printf ("Stack trace:\r\nFrame Function Args\r\n");
|
||||||
for (i = 0; i < 16 && thestack++; i++)
|
for (i = 0; i < 16 && thestack++; i++)
|
||||||
{
|
{
|
||||||
@ -349,7 +349,8 @@ cygwin_stackdump ()
|
|||||||
CONTEXT c;
|
CONTEXT c;
|
||||||
c.ContextFlags = CONTEXT_FULL;
|
c.ContextFlags = CONTEXT_FULL;
|
||||||
GetThreadContext (GetCurrentThread (), &c);
|
GetThreadContext (GetCurrentThread (), &c);
|
||||||
stackdump (c.Ebp);
|
cygwin_exception exc (c.Ebp);
|
||||||
|
exc.dumpstack ();
|
||||||
}
|
}
|
||||||
|
|
||||||
#define TIME_TO_WAIT_FOR_DEBUGGER 10000
|
#define TIME_TO_WAIT_FOR_DEBUGGER 10000
|
||||||
@ -484,7 +485,7 @@ exception::handle (EXCEPTION_RECORD *e, exception_list *frame, CONTEXT *in, void
|
|||||||
if (exit_state || e->ExceptionFlags)
|
if (exit_state || e->ExceptionFlags)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
siginfo_t si = {0};
|
siginfo_t si = {};
|
||||||
si.si_code = SI_KERNEL;
|
si.si_code = SI_KERNEL;
|
||||||
/* Coerce win32 value to posix value. */
|
/* Coerce win32 value to posix value. */
|
||||||
switch (e->ExceptionCode)
|
switch (e->ExceptionCode)
|
||||||
@ -594,17 +595,12 @@ exception::handle (EXCEPTION_RECORD *e, exception_list *frame, CONTEXT *in, void
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (me.andreas)
|
||||||
|
me.andreas->leave (); /* Return from a "san" caught fault */
|
||||||
|
|
||||||
debug_printf ("In cygwin_except_handler exception %p at %p sp %p", e->ExceptionCode, in->Eip, in->Esp);
|
debug_printf ("In cygwin_except_handler exception %p at %p sp %p", e->ExceptionCode, in->Eip, in->Esp);
|
||||||
debug_printf ("In cygwin_except_handler signal %d at %p", si.si_signo, in->Eip);
|
debug_printf ("In cygwin_except_handler signal %d at %p", si.si_signo, in->Eip);
|
||||||
|
|
||||||
bool masked = !!(me.sigmask & SIGTOMASK (si.si_signo));
|
|
||||||
if (masked)
|
|
||||||
syscall_printf ("signal %d, masked %p", si.si_signo,
|
|
||||||
global_sigs[si.si_signo].sa_mask);
|
|
||||||
|
|
||||||
debug_printf ("In cygwin_except_handler calling %p",
|
|
||||||
global_sigs[si.si_signo].sa_handler);
|
|
||||||
|
|
||||||
DWORD *ebp = (DWORD *) in->Esp;
|
DWORD *ebp = (DWORD *) in->Esp;
|
||||||
for (DWORD *bpend = (DWORD *) __builtin_frame_address (0); ebp > bpend; ebp--)
|
for (DWORD *bpend = (DWORD *) __builtin_frame_address (0); ebp > bpend; ebp--)
|
||||||
if (*ebp == in->SegCs && ebp[-1] == in->Eip)
|
if (*ebp == in->SegCs && ebp[-1] == in->Eip)
|
||||||
@ -613,9 +609,6 @@ exception::handle (EXCEPTION_RECORD *e, exception_list *frame, CONTEXT *in, void
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (me.andreas)
|
|
||||||
me.andreas->leave (); /* Return from a "san" caught fault */
|
|
||||||
|
|
||||||
me.copy_context (in);
|
me.copy_context (in);
|
||||||
|
|
||||||
/* Temporarily replace windows top level SEH with our own handler.
|
/* Temporarily replace windows top level SEH with our own handler.
|
||||||
@ -623,63 +616,38 @@ exception::handle (EXCEPTION_RECORD *e, exception_list *frame, CONTEXT *in, void
|
|||||||
will be removed automatically after our exception handler returns. */
|
will be removed automatically after our exception handler returns. */
|
||||||
_except_list->handler = handle;
|
_except_list->handler = handle;
|
||||||
|
|
||||||
if (masked
|
/* Another exception could happen while tracing or while exiting.
|
||||||
|| &me == _sig_tls
|
Only do this once. */
|
||||||
|| !cygwin_finished_initializing
|
if (recursed++)
|
||||||
|| (void *) global_sigs[si.si_signo].sa_handler == (void *) SIG_DFL
|
system_printf ("Error while dumping state (probably corrupted stack)");
|
||||||
|| (void *) global_sigs[si.si_signo].sa_handler == (void *) SIG_IGN
|
else if (!try_to_debug (0))
|
||||||
|| (void *) global_sigs[si.si_signo].sa_handler == (void *) SIG_ERR)
|
rtl_unwind (frame, e);
|
||||||
|
else
|
||||||
{
|
{
|
||||||
/* Print the exception to the console */
|
debugging = true;
|
||||||
if (!myself->cygstarted)
|
return 0;
|
||||||
for (int i = 0; status_info[i].name; i++)
|
|
||||||
if (status_info[i].code == e->ExceptionCode)
|
|
||||||
{
|
|
||||||
system_printf ("Exception: %s", status_info[i].name);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Another exception could happen while tracing or while exiting.
|
|
||||||
Only do this once. */
|
|
||||||
if (recursed++)
|
|
||||||
system_printf ("Error while dumping state (probably corrupted stack)");
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (try_to_debug (0))
|
|
||||||
{
|
|
||||||
debugging = true;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
rtl_unwind (frame, e);
|
|
||||||
if (cygheap->rlim_core > 0UL)
|
|
||||||
stackdump ((DWORD) ebp, in, e);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((NTSTATUS) e->ExceptionCode == STATUS_ACCESS_VIOLATION)
|
|
||||||
{
|
|
||||||
int error_code = 0;
|
|
||||||
if (si.si_code == SEGV_ACCERR) /* Address present */
|
|
||||||
error_code |= 1;
|
|
||||||
if (e->ExceptionInformation[0]) /* Write access */
|
|
||||||
error_code |= 2;
|
|
||||||
if (!me.inside_kernel (in)) /* User space */
|
|
||||||
error_code |= 4;
|
|
||||||
klog (LOG_INFO, "%s[%d]: segfault at %08x rip %08x rsp %08x error %d",
|
|
||||||
__progname, myself->pid,
|
|
||||||
e->ExceptionInformation[1], in->Eip, in->Esp,
|
|
||||||
error_code);
|
|
||||||
}
|
|
||||||
|
|
||||||
setup_signal_exit ((cygheap->rlim_core > 0UL ? 0x80 : 0) | si.si_signo);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
si.si_addr = (si.si_signo == SIGSEGV || si.si_signo == SIGBUS
|
/* FIXME: Probably should be handled in sigpacket::process */
|
||||||
? (void *) e->ExceptionInformation[1]
|
if ((NTSTATUS) e->ExceptionCode == STATUS_ACCESS_VIOLATION)
|
||||||
: (void *) in->Eip);
|
{
|
||||||
si.si_errno = si.si_pid = si.si_uid = 0;
|
int error_code = 0;
|
||||||
|
if (si.si_code == SEGV_ACCERR) /* Address present */
|
||||||
|
error_code |= 1;
|
||||||
|
if (e->ExceptionInformation[0]) /* Write access */
|
||||||
|
error_code |= 2;
|
||||||
|
if (!me.inside_kernel (in)) /* User space */
|
||||||
|
error_code |= 4;
|
||||||
|
klog (LOG_INFO, "%s[%d]: segfault at %08x rip %08x rsp %08x error %d",
|
||||||
|
__progname, myself->pid, e->ExceptionInformation[1],
|
||||||
|
in->Eip, in->Esp, error_code);
|
||||||
|
}
|
||||||
|
|
||||||
|
cygwin_exception exc ((DWORD) ebp, in, e);
|
||||||
|
si.si_cyg = (void *) &exc;
|
||||||
|
si.si_addr = (void *) in->Eip;
|
||||||
me.incyg++;
|
me.incyg++;
|
||||||
sig_send (NULL, si, &me); // Signal myself
|
sig_send (NULL, si, &me); /* Signal myself */
|
||||||
me.incyg--;
|
me.incyg--;
|
||||||
e->ExceptionFlags = 0;
|
e->ExceptionFlags = 0;
|
||||||
return 0;
|
return 0;
|
||||||
@ -962,7 +930,7 @@ ctrl_c_handler (DWORD type)
|
|||||||
list goad. */
|
list goad. */
|
||||||
if (global_sigs[SIGHUP].sa_handler != SIG_DFL)
|
if (global_sigs[SIGHUP].sa_handler != SIG_DFL)
|
||||||
{
|
{
|
||||||
sig_send (myself_nowait, SIGHUP);
|
sig_send (myself, SIGHUP);
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
return FALSE;
|
return FALSE;
|
||||||
@ -1115,6 +1083,59 @@ set_signal_mask (sigset_t& setmask, sigset_t newmask)
|
|||||||
sig_dispatch_pending (true);
|
sig_dispatch_pending (true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Exit due to a signal. Should only be called from the signal thread. */
|
||||||
|
extern "C" {
|
||||||
|
static void
|
||||||
|
signal_exit (int sig, siginfo_t *si)
|
||||||
|
{
|
||||||
|
debug_printf ("exiting due to signal %d", sig);
|
||||||
|
exit_state = ES_SIGNAL_EXIT;
|
||||||
|
|
||||||
|
if (have_execed)
|
||||||
|
{
|
||||||
|
sigproc_printf ("terminating captive process");
|
||||||
|
TerminateProcess (ch_spawn, sigExeced = sig);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cygheap->rlim_core > 0UL)
|
||||||
|
switch (sig)
|
||||||
|
{
|
||||||
|
case SIGABRT:
|
||||||
|
case SIGBUS:
|
||||||
|
case SIGFPE:
|
||||||
|
case SIGILL:
|
||||||
|
case SIGQUIT:
|
||||||
|
case SIGSEGV:
|
||||||
|
case SIGSYS:
|
||||||
|
case SIGTRAP:
|
||||||
|
case SIGXCPU:
|
||||||
|
case SIGXFSZ:
|
||||||
|
if (try_to_debug ())
|
||||||
|
break;
|
||||||
|
if (si->si_code != SI_USER && si->si_cyg)
|
||||||
|
((cygwin_exception *) si->si_cyg)->dumpstack ();
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cygwin_exception exc (_my_tls.thread_context.ebp);
|
||||||
|
exc.dumpstack ();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
lock_process until_exit (true);
|
||||||
|
|
||||||
|
if (have_execed || exit_state > ES_PROCESS_LOCKED)
|
||||||
|
myself.exit (sig);
|
||||||
|
|
||||||
|
/* Starve other threads in a vain attempt to stop them from doing something
|
||||||
|
stupid. */
|
||||||
|
SetThreadPriority (GetCurrentThread (), THREAD_PRIORITY_TIME_CRITICAL);
|
||||||
|
|
||||||
|
sigproc_printf ("about to call do_exit (%x)", sig);
|
||||||
|
do_exit (sig);
|
||||||
|
}
|
||||||
|
} /* extern "C" */
|
||||||
|
|
||||||
int __stdcall
|
int __stdcall
|
||||||
sigpacket::process ()
|
sigpacket::process ()
|
||||||
{
|
{
|
||||||
@ -1224,18 +1245,39 @@ sigpacket::process ()
|
|||||||
stop:
|
stop:
|
||||||
handler = (void *) sig_handle_tty_stop;
|
handler = (void *) sig_handle_tty_stop;
|
||||||
thissig = dummy;
|
thissig = dummy;
|
||||||
|
goto dosig;
|
||||||
|
|
||||||
|
exit_sig:
|
||||||
|
handler = (void *) signal_exit;
|
||||||
|
thissig.sa_flags |= SA_SIGINFO;
|
||||||
|
if (si.si_signo == SIGKILL)
|
||||||
|
goto dispatch_sig;
|
||||||
|
|
||||||
dosig:
|
dosig:
|
||||||
if (ISSTATE (myself, PID_STOPPED) && !continue_now)
|
if (ISSTATE (myself, PID_STOPPED) && !continue_now)
|
||||||
rc = -1; /* No signals delivered if stopped */
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
/* Dispatch to the appropriate function. */
|
rc = -1; /* No signals delivered if stopped */
|
||||||
sigproc_printf ("signal %d, signal handler %p", si.si_signo, handler);
|
goto done;
|
||||||
rc = setup_handler (handler, thissig, tls);
|
|
||||||
continue_now = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dispatch_sig:
|
||||||
|
/* Do stuff for gdb */
|
||||||
|
if (si.si_code == SI_USER || !si.si_cyg)
|
||||||
|
{
|
||||||
|
CONTEXT c;
|
||||||
|
c.ContextFlags = CONTEXT_FULL;
|
||||||
|
GetThreadContext (hMainThread, &c);
|
||||||
|
_my_tls.copy_context (&c);
|
||||||
|
|
||||||
|
/* Tell gdb that we got a signal. Presumably, gdb already noticed this
|
||||||
|
if we hit an exception. */
|
||||||
|
_my_tls.signal_debugger (si.si_signo);
|
||||||
|
}
|
||||||
|
/* Dispatch to the appropriate function. */
|
||||||
|
sigproc_printf ("signal %d, signal handler %p", si.si_signo, handler);
|
||||||
|
rc = setup_handler (handler, thissig, tls);
|
||||||
|
continue_now = false;
|
||||||
|
|
||||||
done:
|
done:
|
||||||
if (continue_now)
|
if (continue_now)
|
||||||
{
|
{
|
||||||
@ -1245,10 +1287,6 @@ done:
|
|||||||
sigproc_printf ("returning %d", rc);
|
sigproc_printf ("returning %d", rc);
|
||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
exit_sig:
|
|
||||||
sigproc_printf ("setting up for exit with signal %d", si.si_signo);
|
|
||||||
setup_signal_exit (si.si_signo);
|
|
||||||
return rc;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/* signal.h
|
/* signal.h
|
||||||
|
|
||||||
Copyright 2004, 2005, 2006, 2011 Red Hat, Inc.
|
Copyright 2004, 2005, 2006, 2011, 2012, 2013 Red Hat, Inc.
|
||||||
|
|
||||||
This file is part of Cygwin.
|
This file is part of Cygwin.
|
||||||
|
|
||||||
@ -127,8 +127,13 @@ typedef struct
|
|||||||
clock_t si_stime; /* system time */
|
clock_t si_stime; /* system time */
|
||||||
};
|
};
|
||||||
|
|
||||||
/* core dumping signals */
|
__extension__ struct
|
||||||
void *si_addr; /* faulting address */
|
{
|
||||||
|
/* core dumping signals */
|
||||||
|
void *si_addr; /* faulting address */
|
||||||
|
void *si_cyg; /* pointer to block containing
|
||||||
|
cygwin-special info */
|
||||||
|
};
|
||||||
};
|
};
|
||||||
} siginfo_t;
|
} siginfo_t;
|
||||||
#pragma pack(pop)
|
#pragma pack(pop)
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/* sigproc.cc: inter/intra signal and sub process handler
|
/* sigproc.cc: inter/intra signal and sub process handler
|
||||||
|
|
||||||
Copyright 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
|
Copyright 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007,
|
||||||
2006, 2007, 2008, 2009, 2010, 2011, 2012 Red Hat, Inc.
|
2008, 2009, 2010, 2011, 2012, 2013 Red Hat, Inc.
|
||||||
|
|
||||||
This file is part of Cygwin.
|
This file is part of Cygwin.
|
||||||
|
|
||||||
@ -31,7 +31,7 @@ details. */
|
|||||||
#define WSSC 60000 // Wait for signal completion
|
#define WSSC 60000 // Wait for signal completion
|
||||||
#define WPSP 40000 // Wait for proc_subproc mutex
|
#define WPSP 40000 // Wait for proc_subproc mutex
|
||||||
|
|
||||||
#define no_signals_available(x) (!my_sendsig || ((x) && myself->exitcode & EXITCODE_SET) || (&_my_tls == _sig_tls))
|
#define no_signals_available() (exit_state || (myself->exitcode & EXITCODE_SET) || (&_my_tls == _sig_tls))
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Global variables
|
* Global variables
|
||||||
@ -61,7 +61,6 @@ _cygtls NO_COPY *_sig_tls;
|
|||||||
|
|
||||||
Static HANDLE my_sendsig;
|
Static HANDLE my_sendsig;
|
||||||
Static HANDLE my_readsig;
|
Static HANDLE my_readsig;
|
||||||
Static int signal_exit_code;
|
|
||||||
|
|
||||||
/* Function declarations */
|
/* Function declarations */
|
||||||
static int __stdcall checkstate (waitq *) __attribute__ ((regparm (1)));
|
static int __stdcall checkstate (waitq *) __attribute__ ((regparm (1)));
|
||||||
@ -354,53 +353,6 @@ _cygtls::remove_wq (DWORD wait)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void
|
|
||||||
close_my_readsig ()
|
|
||||||
{
|
|
||||||
HANDLE h;
|
|
||||||
if ((h = InterlockedExchangePointer (&my_readsig, NULL)))
|
|
||||||
ForceCloseHandle1 (h, my_readsig);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Exit due to a signal, even in presence of more exceptions. We used to just
|
|
||||||
call exit, but a SIGSEGV shouldn't cause atexit routines to run.
|
|
||||||
Should only be called from the signal thread. */
|
|
||||||
void
|
|
||||||
_cygtls::signal_exit (int rc)
|
|
||||||
{
|
|
||||||
signal_debugger (rc & 0x7f);
|
|
||||||
|
|
||||||
if (rc == SIGQUIT || rc == SIGABRT)
|
|
||||||
{
|
|
||||||
CONTEXT c;
|
|
||||||
c.ContextFlags = CONTEXT_FULL;
|
|
||||||
GetThreadContext (hMainThread, &c);
|
|
||||||
copy_context (&c);
|
|
||||||
if (cygheap->rlim_core > 0UL)
|
|
||||||
rc |= 0x80;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (have_execed)
|
|
||||||
{
|
|
||||||
sigproc_printf ("terminating captive process");
|
|
||||||
TerminateProcess (ch_spawn, sigExeced = rc);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((rc & 0x80) && !try_to_debug ())
|
|
||||||
stackdump (thread_context.ebp, true);
|
|
||||||
|
|
||||||
lock_process until_exit (true);
|
|
||||||
if (have_execed || exit_state > ES_PROCESS_LOCKED)
|
|
||||||
myself.exit (rc);
|
|
||||||
|
|
||||||
/* Starve other threads in a vain attempt to stop them from doing something
|
|
||||||
stupid. */
|
|
||||||
SetThreadPriority (GetCurrentThread (), THREAD_PRIORITY_TIME_CRITICAL);
|
|
||||||
|
|
||||||
sigproc_printf ("about to call do_exit (%x)", rc);
|
|
||||||
do_exit (rc);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Terminate the wait_subproc thread.
|
/* Terminate the wait_subproc thread.
|
||||||
Called on process exit.
|
Called on process exit.
|
||||||
Also called by spawn_guts to disassociate any subprocesses from this
|
Also called by spawn_guts to disassociate any subprocesses from this
|
||||||
@ -523,36 +475,11 @@ sigproc_terminate (exit_states es)
|
|||||||
exit_states prior_exit_state = exit_state;
|
exit_states prior_exit_state = exit_state;
|
||||||
exit_state = es;
|
exit_state = es;
|
||||||
if (!cygwin_finished_initializing)
|
if (!cygwin_finished_initializing)
|
||||||
sigproc_printf ("don't worry about signal thread");
|
/* nothing to do */;
|
||||||
else if (prior_exit_state >= ES_FINAL)
|
else if (prior_exit_state >= ES_FINAL)
|
||||||
sigproc_printf ("already performed");
|
sigproc_printf ("already performed");
|
||||||
else
|
else
|
||||||
{
|
proc_terminate (); // clean up process stuff
|
||||||
sigproc_printf ("entering");
|
|
||||||
sig_send (myself_nowait, __SIGEXIT);
|
|
||||||
proc_terminate (); // clean up process stuff
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Set up stuff so that the signal thread will know that we are
|
|
||||||
exiting due to a signal. */
|
|
||||||
void
|
|
||||||
setup_signal_exit (int sig)
|
|
||||||
{
|
|
||||||
signal_exit_code = sig; /* Tell wait_sig() that we are exiting. */
|
|
||||||
exit_state = ES_SIGNAL_EXIT; /* Tell the rest of the world that we are exiting. */
|
|
||||||
|
|
||||||
if (&_my_tls != _sig_tls)
|
|
||||||
{
|
|
||||||
sigpacket sp = {};
|
|
||||||
sp.si.si_signo = __SIGEXIT;
|
|
||||||
DWORD len;
|
|
||||||
/* Write a packet to the wait_sig thread. It will eventuall cause
|
|
||||||
the process to exit too. So just wait for that to happen after
|
|
||||||
sending the packet. */
|
|
||||||
WriteFile (my_sendsig, &sp, sizeof (sp), &len, NULL);
|
|
||||||
Sleep (INFINITE);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Exit the current thread very carefully.
|
/* Exit the current thread very carefully.
|
||||||
@ -576,7 +503,7 @@ exit_thread (DWORD res)
|
|||||||
}
|
}
|
||||||
ProtectHandle1 (h, exit_thread);
|
ProtectHandle1 (h, exit_thread);
|
||||||
siginfo_t si = {__SIGTHREADEXIT, SI_KERNEL};
|
siginfo_t si = {__SIGTHREADEXIT, SI_KERNEL};
|
||||||
si.si_value.sival_ptr = h;
|
si.si_cyg = h;
|
||||||
lock_process for_now; /* May block indefinitely if we're exiting. */
|
lock_process for_now; /* May block indefinitely if we're exiting. */
|
||||||
if (exit_state)
|
if (exit_state)
|
||||||
{
|
{
|
||||||
@ -599,7 +526,7 @@ sig_send (_pinfo *p, int sig, _cygtls *tid)
|
|||||||
/* nothing */;
|
/* nothing */;
|
||||||
else if (sig == __SIGFLUSH || sig == __SIGFLUSHFAST)
|
else if (sig == __SIGFLUSH || sig == __SIGFLUSHFAST)
|
||||||
return 0;
|
return 0;
|
||||||
else if (sig == __SIGNOHOLD || sig == __SIGEXIT)
|
else if (sig == __SIGNOHOLD)
|
||||||
{
|
{
|
||||||
SetEvent (sig_hold);
|
SetEvent (sig_hold);
|
||||||
sigheld = false;
|
sigheld = false;
|
||||||
@ -611,10 +538,9 @@ sig_send (_pinfo *p, int sig, _cygtls *tid)
|
|||||||
#endif
|
#endif
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
siginfo_t si = {0};
|
siginfo_t si = {};
|
||||||
si.si_signo = sig;
|
si.si_signo = sig;
|
||||||
si.si_code = SI_KERNEL;
|
si.si_code = SI_KERNEL;
|
||||||
si.si_pid = si.si_uid = si.si_errno = 0;
|
|
||||||
return sig_send (p, si, tid);
|
return sig_send (p, si, tid);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -648,7 +574,7 @@ sig_send (_pinfo *p, siginfo_t& si, _cygtls *tls)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (no_signals_available (si.si_signo != __SIGEXIT))
|
if (no_signals_available ())
|
||||||
{
|
{
|
||||||
set_errno (EAGAIN);
|
set_errno (EAGAIN);
|
||||||
goto out; // Either exiting or not yet initializing
|
goto out; // Either exiting or not yet initializing
|
||||||
@ -778,7 +704,7 @@ sig_send (_pinfo *p, siginfo_t& si, _cygtls *tls)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (no_signals_available (true))
|
if (no_signals_available ())
|
||||||
sigproc_printf ("I'm going away now");
|
sigproc_printf ("I'm going away now");
|
||||||
else if (!p->exec_sendsig)
|
else if (!p->exec_sendsig)
|
||||||
system_printf ("error sending signal %d to pid %d, pipe handle %p, %E",
|
system_printf ("error sending signal %d to pid %d, pipe handle %p, %E",
|
||||||
@ -818,7 +744,7 @@ sig_send (_pinfo *p, siginfo_t& si, _cygtls *tls)
|
|||||||
rc = 0; // Successful exit
|
rc = 0; // Successful exit
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (!no_signals_available (true))
|
if (!no_signals_available ())
|
||||||
system_printf ("wait for sig_complete event failed, signal %d, rc %d, %E",
|
system_printf ("wait for sig_complete event failed, signal %d, rc %d, %E",
|
||||||
si.si_signo, rc);
|
si.si_signo, rc);
|
||||||
set_errno (ENOSYS);
|
set_errno (ENOSYS);
|
||||||
@ -1390,12 +1316,6 @@ wait_sig (VOID *)
|
|||||||
WaitForSingleObject (sig_hold, INFINITE);
|
WaitForSingleObject (sig_hold, INFINITE);
|
||||||
|
|
||||||
DWORD nb;
|
DWORD nb;
|
||||||
/* If signal_exit_code is set then we are shutting down due to a signal.
|
|
||||||
We'll exit this loop iff there is nothing more in the signal queue. */
|
|
||||||
if (signal_exit_code
|
|
||||||
&& (!PeekNamedPipe (my_readsig, NULL, 0, NULL, &nb, NULL) || !nb))
|
|
||||||
break;
|
|
||||||
|
|
||||||
pack.sigtls = NULL;
|
pack.sigtls = NULL;
|
||||||
if (!ReadFile (my_readsig, &pack, sizeof (pack), &nb, NULL))
|
if (!ReadFile (my_readsig, &pack, sizeof (pack), &nb, NULL))
|
||||||
break;
|
break;
|
||||||
@ -1415,8 +1335,9 @@ wait_sig (VOID *)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (signal_exit_code && pack.si.si_signo > 0)
|
/* Don't process signals when we start exiting */
|
||||||
continue; /* No more real signals allowed */
|
if (exit_state && pack.si.si_signo)
|
||||||
|
continue;
|
||||||
|
|
||||||
sigset_t dummy_mask;
|
sigset_t dummy_mask;
|
||||||
if (!pack.mask)
|
if (!pack.mask)
|
||||||
@ -1459,10 +1380,6 @@ wait_sig (VOID *)
|
|||||||
clearwait = true;
|
clearwait = true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case __SIGEXIT:
|
|
||||||
my_sendsig = NULL;
|
|
||||||
sigproc_printf ("saw __SIGEXIT");
|
|
||||||
break; /* handle below */
|
|
||||||
case __SIGSETPGRP:
|
case __SIGSETPGRP:
|
||||||
init_console_handler (true);
|
init_console_handler (true);
|
||||||
break;
|
break;
|
||||||
@ -1475,7 +1392,7 @@ wait_sig (VOID *)
|
|||||||
release the process lock which it held and close it's handle.
|
release the process lock which it held and close it's handle.
|
||||||
See cgf-000017 in DevNotes for more details.
|
See cgf-000017 in DevNotes for more details.
|
||||||
*/
|
*/
|
||||||
HANDLE h = (HANDLE) pack.si.si_value.sival_ptr;
|
HANDLE h = (HANDLE) pack.si.si_cyg;
|
||||||
DWORD res = WaitForSingleObject (h, 5000);
|
DWORD res = WaitForSingleObject (h, 5000);
|
||||||
lock_process::force_release (pack.sigtls);
|
lock_process::force_release (pack.sigtls);
|
||||||
ForceCloseHandle1 (h, exit_thread);
|
ForceCloseHandle1 (h, exit_thread);
|
||||||
@ -1519,20 +1436,5 @@ wait_sig (VOID *)
|
|||||||
sigproc_printf ("signalling pack.wakeup %p", pack.wakeup);
|
sigproc_printf ("signalling pack.wakeup %p", pack.wakeup);
|
||||||
SetEvent (pack.wakeup);
|
SetEvent (pack.wakeup);
|
||||||
}
|
}
|
||||||
if (pack.si.si_signo == __SIGEXIT)
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sigproc_printf ("signal thread exiting");
|
|
||||||
|
|
||||||
my_sendsig = NULL; /* Make no_signals_allowed return true */
|
|
||||||
close_my_readsig (); /* Cause any sig_send's to stop */
|
|
||||||
|
|
||||||
if (signal_exit_code)
|
|
||||||
_my_tls.signal_exit (signal_exit_code);
|
|
||||||
|
|
||||||
/* Just wait for the process to go away. Otherwise, this thread's
|
|
||||||
exit value could be interpreted as the process exit value.
|
|
||||||
See cgf-000017 in DevNotes for more details. */
|
|
||||||
Sleep (INFINITE);
|
|
||||||
}
|
}
|
||||||
|
@ -24,9 +24,8 @@ enum
|
|||||||
__SIGFLUSHFAST = -(NSIG + 6),
|
__SIGFLUSHFAST = -(NSIG + 6),
|
||||||
__SIGHOLD = -(NSIG + 7),
|
__SIGHOLD = -(NSIG + 7),
|
||||||
__SIGNOHOLD = -(NSIG + 8),
|
__SIGNOHOLD = -(NSIG + 8),
|
||||||
__SIGEXIT = -(NSIG + 9),
|
__SIGSETPGRP = -(NSIG + 9),
|
||||||
__SIGSETPGRP = -(NSIG + 10),
|
__SIGTHREADEXIT = -(NSIG + 10)
|
||||||
__SIGTHREADEXIT = -(NSIG + 11)
|
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user