4
0
mirror of git://sourceware.org/git/newlib-cygwin.git synced 2025-01-29 02:20:21 +08:00
Christopher Faylor ca77b848e7 * 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.
2013-01-02 18:34:06 +00:00

176 lines
4.2 KiB
C++

/* sigproc.h
Copyright 1997, 1998, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
2011, 2012 Red Hat, Inc.
This file is part of Cygwin.
This software is a copyrighted work licensed under the terms of the
Cygwin license. Please consult the file "CYGWIN_LICENSE" for
details. */
#pragma once
#include <signal.h>
#include "sync.h"
#ifdef NSIG
enum
{
__SIGFLUSH = -(NSIG + 1),
__SIGSTRACE = -(NSIG + 2),
__SIGCOMMUNE = -(NSIG + 3),
__SIGPENDING = -(NSIG + 4),
__SIGDELETE = -(NSIG + 5),
__SIGFLUSHFAST = -(NSIG + 6),
__SIGHOLD = -(NSIG + 7),
__SIGNOHOLD = -(NSIG + 8),
__SIGSETPGRP = -(NSIG + 9),
__SIGTHREADEXIT = -(NSIG + 10)
};
#endif
#define SIG_BAD_MASK (1 << (SIGKILL - 1))
enum procstuff
{
PROC_ADDCHILD = 1, // add a new subprocess to list
PROC_REATTACH_CHILD = 2, // reattach after exec
PROC_EXEC_CLEANUP = 3, // cleanup waiting children after exec
PROC_DETACHED_CHILD = 4, // set up a detached child
PROC_CLEARWAIT = 5, // clear all waits - signal arrived
PROC_WAIT = 6, // setup for wait() for subproc
PROC_EXECING = 7, // used to get a lock when execing
PROC_NOTHING = 8 // nothing, really
};
struct sigpacket
{
siginfo_t si;
pid_t pid;
class _cygtls *sigtls;
sigset_t *mask;
union
{
HANDLE wakeup;
HANDLE thread_handle;
struct sigpacket *next;
};
int __stdcall process () __attribute__ ((regparm (1)));
int setup_handler (void *, struct sigaction&, _cygtls *)
__attribute__ ((regparm (3)));
};
void __stdcall sig_dispatch_pending (bool fast = false)
__attribute__ ((regparm (1)));
void set_signal_mask (sigset_t&, sigset_t) __attribute__ ((regparm (2)));
int __stdcall handle_sigprocmask (int sig, const sigset_t *set,
sigset_t *oldset, sigset_t& opmask)
__attribute__ ((regparm (3)));
void __stdcall sig_clear (int) __attribute__ ((regparm (1)));
void __stdcall sig_set_pending (int) __attribute__ ((regparm (1)));
int __stdcall handle_sigsuspend (sigset_t);
int __stdcall proc_subproc (DWORD, DWORD) __attribute__ ((regparm (2)));
class _pinfo;
void __stdcall proc_terminate ();
void __stdcall sigproc_init ();
#ifdef __INSIDE_CYGWIN__
void __stdcall sigproc_terminate (enum exit_states);
#endif
bool __stdcall pid_exists (pid_t) __attribute__ ((regparm(1)));
int __stdcall sig_send (_pinfo *, siginfo_t&, class _cygtls * = NULL) __attribute__ ((regparm (3)));
int __stdcall sig_send (_pinfo *, int, class _cygtls * = NULL) __attribute__ ((regparm (3)));
void __stdcall signal_fixup_after_exec ();
void __stdcall sigalloc ();
int kill_pgrp (pid_t, siginfo_t&);
int killsys (pid_t, int);
void exit_thread (DWORD) __attribute__ ((regparm (1), noreturn));
void setup_signal_exit (int) __attribute__ ((regparm (1)));
extern "C" void sigdelayed ();
extern char myself_nowait_dummy[];
extern struct sigaction *global_sigs;
class lock_signals
{
bool worked;
public:
lock_signals ()
{
worked = sig_send (NULL, __SIGHOLD) == 0;
}
operator int () const
{
return worked;
}
void dont_bother ()
{
worked = false;
}
~lock_signals ()
{
if (worked)
sig_send (NULL, __SIGNOHOLD);
}
};
class lock_pthread
{
bool bother;
public:
lock_pthread (): bother (1)
{
pthread::atforkprepare ();
}
void dont_bother ()
{
bother = false;
}
~lock_pthread ()
{
if (bother)
pthread::atforkparent ();
}
};
class hold_everything
{
bool ischild;
/* Note the order of the locks below. It is important,
to avoid races, that the lock order be preserved.
pthread is first because it serves as a master lock
against other forks being attempted while this one is active.
signals is next to stop signal processing for the duration
of the fork.
process is last. If it is put before signals, then a deadlock
could be introduced if the process attempts to exit due to a signal. */
lock_pthread pthread;
lock_signals signals;
lock_process process;
public:
hold_everything (bool x = false): ischild (x) {}
operator int () const {return signals;}
~hold_everything()
{
if (ischild)
{
pthread.dont_bother ();
process.dont_bother ();
signals.dont_bother ();
}
}
};
#define myself_nowait ((_pinfo *) myself_nowait_dummy)