* 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
|
||||
|
||||
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
|
||||
Cygwin license. Please consult the file "CYGWIN_LICENSE" for
|
||||
@ -220,7 +220,6 @@ public:
|
||||
__attribute__((regparm(3)));
|
||||
|
||||
bool inside_kernel (CONTEXT *);
|
||||
void signal_exit (int) __attribute__ ((noreturn, regparm(2)));
|
||||
void copy_context (CONTEXT *) __attribute__ ((regparm(2)));
|
||||
void signal_debugger (int) __attribute__ ((regparm(2)));
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
/* 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
|
||||
Cygwin license. Please consult the file "CYGWIN_LICENSE" for
|
||||
@ -28,10 +28,15 @@ public:
|
||||
~exception () __attribute__ ((always_inline)) { _except_list = save; }
|
||||
};
|
||||
|
||||
void stackdump (DWORD, CONTEXT * = NULL, EXCEPTION_RECORD * = NULL);
|
||||
extern void inline
|
||||
stackdump (DWORD n, bool)
|
||||
class cygwin_exception
|
||||
{
|
||||
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
|
||||
|
||||
Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
|
||||
2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 Red Hat, Inc.
|
||||
Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
|
||||
2007, 2008, 2009, 2010, 2011, 2012, 2013 Red Hat, Inc.
|
||||
|
||||
This file is part of Cygwin.
|
||||
|
||||
@ -163,8 +163,8 @@ open_stackdumpfile ()
|
||||
|
||||
/* Utilities for dumping the stack, etc. */
|
||||
|
||||
static void
|
||||
dump_exception (EXCEPTION_RECORD *e, CONTEXT *in)
|
||||
void
|
||||
cygwin_exception::dump_exception ()
|
||||
{
|
||||
const char *exception_name = NULL;
|
||||
|
||||
@ -181,15 +181,15 @@ dump_exception (EXCEPTION_RECORD *e, CONTEXT *in)
|
||||
}
|
||||
|
||||
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
|
||||
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",
|
||||
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",
|
||||
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",
|
||||
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. */
|
||||
@ -273,7 +273,7 @@ stack_info::walk ()
|
||||
}
|
||||
|
||||
void
|
||||
stackdump (DWORD ebp, PCONTEXT in, EXCEPTION_RECORD *e)
|
||||
cygwin_exception::dumpstack ()
|
||||
{
|
||||
static bool already_dumped;
|
||||
|
||||
@ -283,11 +283,11 @@ stackdump (DWORD ebp, PCONTEXT in, EXCEPTION_RECORD *e)
|
||||
open_stackdumpfile ();
|
||||
|
||||
if (e)
|
||||
dump_exception (e, in);
|
||||
dump_exception ();
|
||||
|
||||
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");
|
||||
for (i = 0; i < 16 && thestack++; i++)
|
||||
{
|
||||
@ -349,7 +349,8 @@ cygwin_stackdump ()
|
||||
CONTEXT c;
|
||||
c.ContextFlags = CONTEXT_FULL;
|
||||
GetThreadContext (GetCurrentThread (), &c);
|
||||
stackdump (c.Ebp);
|
||||
cygwin_exception exc (c.Ebp);
|
||||
exc.dumpstack ();
|
||||
}
|
||||
|
||||
#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)
|
||||
return 1;
|
||||
|
||||
siginfo_t si = {0};
|
||||
siginfo_t si = {};
|
||||
si.si_code = SI_KERNEL;
|
||||
/* Coerce win32 value to posix value. */
|
||||
switch (e->ExceptionCode)
|
||||
@ -594,17 +595,12 @@ exception::handle (EXCEPTION_RECORD *e, exception_list *frame, CONTEXT *in, void
|
||||
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 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;
|
||||
for (DWORD *bpend = (DWORD *) __builtin_frame_address (0); ebp > bpend; ebp--)
|
||||
if (*ebp == in->SegCs && ebp[-1] == in->Eip)
|
||||
@ -613,9 +609,6 @@ exception::handle (EXCEPTION_RECORD *e, exception_list *frame, CONTEXT *in, void
|
||||
break;
|
||||
}
|
||||
|
||||
if (me.andreas)
|
||||
me.andreas->leave (); /* Return from a "san" caught fault */
|
||||
|
||||
me.copy_context (in);
|
||||
|
||||
/* 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. */
|
||||
_except_list->handler = handle;
|
||||
|
||||
if (masked
|
||||
|| &me == _sig_tls
|
||||
|| !cygwin_finished_initializing
|
||||
|| (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)
|
||||
/* 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))
|
||||
rtl_unwind (frame, e);
|
||||
else
|
||||
{
|
||||
/* Print the exception to the console */
|
||||
if (!myself->cygstarted)
|
||||
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);
|
||||
debugging = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
si.si_addr = (si.si_signo == SIGSEGV || si.si_signo == SIGBUS
|
||||
? (void *) e->ExceptionInformation[1]
|
||||
: (void *) in->Eip);
|
||||
si.si_errno = si.si_pid = si.si_uid = 0;
|
||||
/* FIXME: Probably should be handled in sigpacket::process */
|
||||
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);
|
||||
}
|
||||
|
||||
cygwin_exception exc ((DWORD) ebp, in, e);
|
||||
si.si_cyg = (void *) &exc;
|
||||
si.si_addr = (void *) in->Eip;
|
||||
me.incyg++;
|
||||
sig_send (NULL, si, &me); // Signal myself
|
||||
sig_send (NULL, si, &me); /* Signal myself */
|
||||
me.incyg--;
|
||||
e->ExceptionFlags = 0;
|
||||
return 0;
|
||||
@ -962,7 +930,7 @@ ctrl_c_handler (DWORD type)
|
||||
list goad. */
|
||||
if (global_sigs[SIGHUP].sa_handler != SIG_DFL)
|
||||
{
|
||||
sig_send (myself_nowait, SIGHUP);
|
||||
sig_send (myself, SIGHUP);
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
@ -1115,6 +1083,59 @@ set_signal_mask (sigset_t& setmask, sigset_t newmask)
|
||||
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
|
||||
sigpacket::process ()
|
||||
{
|
||||
@ -1224,18 +1245,39 @@ sigpacket::process ()
|
||||
stop:
|
||||
handler = (void *) sig_handle_tty_stop;
|
||||
thissig = dummy;
|
||||
goto dosig;
|
||||
|
||||
exit_sig:
|
||||
handler = (void *) signal_exit;
|
||||
thissig.sa_flags |= SA_SIGINFO;
|
||||
if (si.si_signo == SIGKILL)
|
||||
goto dispatch_sig;
|
||||
|
||||
dosig:
|
||||
if (ISSTATE (myself, PID_STOPPED) && !continue_now)
|
||||
rc = -1; /* No signals delivered if stopped */
|
||||
else
|
||||
{
|
||||
/* 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;
|
||||
rc = -1; /* No signals delivered if stopped */
|
||||
goto done;
|
||||
}
|
||||
|
||||
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:
|
||||
if (continue_now)
|
||||
{
|
||||
@ -1245,10 +1287,6 @@ done:
|
||||
sigproc_printf ("returning %d", 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
|
||||
|
@ -1,6 +1,6 @@
|
||||
/* 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.
|
||||
|
||||
@ -127,8 +127,13 @@ typedef struct
|
||||
clock_t si_stime; /* system time */
|
||||
};
|
||||
|
||||
/* core dumping signals */
|
||||
void *si_addr; /* faulting address */
|
||||
__extension__ struct
|
||||
{
|
||||
/* core dumping signals */
|
||||
void *si_addr; /* faulting address */
|
||||
void *si_cyg; /* pointer to block containing
|
||||
cygwin-special info */
|
||||
};
|
||||
};
|
||||
} siginfo_t;
|
||||
#pragma pack(pop)
|
||||
|
@ -1,7 +1,7 @@
|
||||
/* sigproc.cc: inter/intra signal and sub process handler
|
||||
|
||||
Copyright 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
|
||||
2006, 2007, 2008, 2009, 2010, 2011, 2012 Red Hat, Inc.
|
||||
Copyright 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007,
|
||||
2008, 2009, 2010, 2011, 2012, 2013 Red Hat, Inc.
|
||||
|
||||
This file is part of Cygwin.
|
||||
|
||||
@ -31,7 +31,7 @@ details. */
|
||||
#define WSSC 60000 // Wait for signal completion
|
||||
#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
|
||||
@ -61,7 +61,6 @@ _cygtls NO_COPY *_sig_tls;
|
||||
|
||||
Static HANDLE my_sendsig;
|
||||
Static HANDLE my_readsig;
|
||||
Static int signal_exit_code;
|
||||
|
||||
/* Function declarations */
|
||||
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.
|
||||
Called on process exit.
|
||||
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_state = es;
|
||||
if (!cygwin_finished_initializing)
|
||||
sigproc_printf ("don't worry about signal thread");
|
||||
/* nothing to do */;
|
||||
else if (prior_exit_state >= ES_FINAL)
|
||||
sigproc_printf ("already performed");
|
||||
else
|
||||
{
|
||||
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);
|
||||
}
|
||||
proc_terminate (); // clean up process stuff
|
||||
}
|
||||
|
||||
/* Exit the current thread very carefully.
|
||||
@ -576,7 +503,7 @@ exit_thread (DWORD res)
|
||||
}
|
||||
ProtectHandle1 (h, exit_thread);
|
||||
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. */
|
||||
if (exit_state)
|
||||
{
|
||||
@ -599,7 +526,7 @@ sig_send (_pinfo *p, int sig, _cygtls *tid)
|
||||
/* nothing */;
|
||||
else if (sig == __SIGFLUSH || sig == __SIGFLUSHFAST)
|
||||
return 0;
|
||||
else if (sig == __SIGNOHOLD || sig == __SIGEXIT)
|
||||
else if (sig == __SIGNOHOLD)
|
||||
{
|
||||
SetEvent (sig_hold);
|
||||
sigheld = false;
|
||||
@ -611,10 +538,9 @@ sig_send (_pinfo *p, int sig, _cygtls *tid)
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
siginfo_t si = {0};
|
||||
siginfo_t si = {};
|
||||
si.si_signo = sig;
|
||||
si.si_code = SI_KERNEL;
|
||||
si.si_pid = si.si_uid = si.si_errno = 0;
|
||||
return sig_send (p, si, tid);
|
||||
}
|
||||
|
||||
@ -648,7 +574,7 @@ sig_send (_pinfo *p, siginfo_t& si, _cygtls *tls)
|
||||
}
|
||||
else
|
||||
{
|
||||
if (no_signals_available (si.si_signo != __SIGEXIT))
|
||||
if (no_signals_available ())
|
||||
{
|
||||
set_errno (EAGAIN);
|
||||
goto out; // Either exiting or not yet initializing
|
||||
@ -778,7 +704,7 @@ sig_send (_pinfo *p, siginfo_t& si, _cygtls *tls)
|
||||
}
|
||||
else
|
||||
{
|
||||
if (no_signals_available (true))
|
||||
if (no_signals_available ())
|
||||
sigproc_printf ("I'm going away now");
|
||||
else if (!p->exec_sendsig)
|
||||
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
|
||||
else
|
||||
{
|
||||
if (!no_signals_available (true))
|
||||
if (!no_signals_available ())
|
||||
system_printf ("wait for sig_complete event failed, signal %d, rc %d, %E",
|
||||
si.si_signo, rc);
|
||||
set_errno (ENOSYS);
|
||||
@ -1390,12 +1316,6 @@ wait_sig (VOID *)
|
||||
WaitForSingleObject (sig_hold, INFINITE);
|
||||
|
||||
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;
|
||||
if (!ReadFile (my_readsig, &pack, sizeof (pack), &nb, NULL))
|
||||
break;
|
||||
@ -1415,8 +1335,9 @@ wait_sig (VOID *)
|
||||
continue;
|
||||
}
|
||||
|
||||
if (signal_exit_code && pack.si.si_signo > 0)
|
||||
continue; /* No more real signals allowed */
|
||||
/* Don't process signals when we start exiting */
|
||||
if (exit_state && pack.si.si_signo)
|
||||
continue;
|
||||
|
||||
sigset_t dummy_mask;
|
||||
if (!pack.mask)
|
||||
@ -1459,10 +1380,6 @@ wait_sig (VOID *)
|
||||
clearwait = true;
|
||||
}
|
||||
break;
|
||||
case __SIGEXIT:
|
||||
my_sendsig = NULL;
|
||||
sigproc_printf ("saw __SIGEXIT");
|
||||
break; /* handle below */
|
||||
case __SIGSETPGRP:
|
||||
init_console_handler (true);
|
||||
break;
|
||||
@ -1475,7 +1392,7 @@ wait_sig (VOID *)
|
||||
release the process lock which it held and close it's handle.
|
||||
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);
|
||||
lock_process::force_release (pack.sigtls);
|
||||
ForceCloseHandle1 (h, exit_thread);
|
||||
@ -1519,20 +1436,5 @@ wait_sig (VOID *)
|
||||
sigproc_printf ("signalling pack.wakeup %p", 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),
|
||||
__SIGHOLD = -(NSIG + 7),
|
||||
__SIGNOHOLD = -(NSIG + 8),
|
||||
__SIGEXIT = -(NSIG + 9),
|
||||
__SIGSETPGRP = -(NSIG + 10),
|
||||
__SIGTHREADEXIT = -(NSIG + 11)
|
||||
__SIGSETPGRP = -(NSIG + 9),
|
||||
__SIGTHREADEXIT = -(NSIG + 10)
|
||||
};
|
||||
#endif
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user