* cygwin/include/signal.h: Add copyright notice.

* cygwin.din: Make clock SIGFE.  Add clock_gettime, sigwaitinfo, timer_create,
timer_delete, timer_settime.
* include/cygwin/version.h: Reflect above additions.
* fork.cc (fork_child): Call fixup_timers_after_fork.
* signal.cc (sigwait): Remove unused variable.
* timer.cc: New file.
(clock_gettime): Define new function.
(timer_tracker): Define new struct used by timer functions.
(timer_tracker::timer_tracker): New function.
(to_us): New function.
(timer_thread): New function.
(timer_tracker::settime): New function.
(timer_create): New function.
(timer_settime): New function.
(timer_delete): New function.
(fixup_timers_after_fork): New function.
* cygthread.cc: Bump thread count.
* signal.cc (sigwaitinfo): Define new function.
(sigwait): Redefine based on sigwaitinfo.
* include/cygwin/signal.h (sigwaitinfo): Declare.
(sigwait): Ditto.
* dtable.cc (dtable::vfork_parent_restore): Avoid double close of ctty when
ctty == ctty_on_hold.
* cygtls.h (_threadinfo::threadkill): New element.
(_threadinfo::set_threadkill): Declare new function.
(_threadinfo::reset_threadkill): Declare new function.
* dcrt0.cc (dcrt0_1): Call here so that it will be possible to attach to
running process with #(*& Windows Me/9x.
(initial_env): Try to initialize strace if uninitialized.
* gendef: Don't zero signal if threadkill is set since that will happen in the
called function.
* signal.cc (sigwait): Ensure cleanup in error conditions.
* sigproc.cc (sig_send): Clear packet mask storage.
(wait_subproc): Fill in child exit code in siginfo_t structure.
* thread.cc (pthread_kill): Set threadkill flag.
* tlsoffsets.h: Regenerate.  Throughout, use siginfo_t to fill out all signal
information for "kernel" signals.
* cygtls.h (_threadinfo::set_siginfo): Declare new function.
* cygtls.cc (_threadinfo::set_siginfo): Define new function.
* dcrt0.cc (do_exit): Accommodate siginfo_t considerations.
* exceptions.cc (handle_exceptions): Ditto.
(sig_handle_tty_stop): Ditto.
(ctrl_c_handler): Use killsys() to send signal.
(sigpacket::process): Rename from sig_handle.  Use siginfo_t field from
sigpacket for everything.
(tty_min::kill_pgrp): Accommodate siginfo_t considerations.
(fhandler_termios::bg_check): Ditto.
* fhandler_tty.cc (fhandler_tty_slave::ioctl): Use killsys() to send signal.
* signal.cc (kill_worker): Rewrite to use siginfo_t second argument.
(kill_pgrp): Ditto.
(kill0): Define new function pulled from kill().
(kill): Rewrite as frontend to kill0.
(killsys): Define new function.
* sigproc.cc (sigelem): Eliminate.
(sigpacket): Move to sigproc.h.  Subsume sigelem.
(pending_signals): Use sigpacket rather than sigelem for everything.
(sig_clear): Ditto.
(wait_sig): Ditto.
(sig_send): Rewrite to use siginfo_t argument.
(sig_send): New function wratpper to sig_send with siginfo_t argument.
(wait_subproc): Accommodate siginfo_t considerations.
* thread.cc (pthread_kill): Ditto.
* sigproc.h (sigpacket): Move here.
(sigpacket::process): Declare "new" function.
(sig_handle): Eliminate declaration.
(sig_send): Declare with new paramaters.
(killsys): Declare new function.
(kill_pgrp): Declare.
* winsup.h: Move some signal-specific stuff to sigproc.h.
* include/cygwin/signal.h: Tweak some siginfo_t stuff.
This commit is contained in:
Christopher Faylor
2004-01-19 05:46:54 +00:00
parent 49fec4c011
commit f6936c48f3
25 changed files with 819 additions and 253 deletions

View File

@ -419,30 +419,56 @@ handle_exceptions (EXCEPTION_RECORD *e0, void *frame, CONTEXT *in0, void *)
RtlUnwind (frame, ret_here, e0, 0);
__asm__ volatile (".equ _ret_here,.");
int sig;
siginfo_t si;
/* Coerce win32 value to posix value. */
switch (e.ExceptionCode)
{
case STATUS_FLOAT_DENORMAL_OPERAND:
case STATUS_FLOAT_DIVIDE_BY_ZERO:
case STATUS_FLOAT_INEXACT_RESULT:
case STATUS_FLOAT_INVALID_OPERATION:
case STATUS_FLOAT_OVERFLOW:
case STATUS_FLOAT_STACK_CHECK:
si.si_signo = SIGFPE;
si.si_sigval.sival_int = FPE_FLTSUB;
break;
case STATUS_FLOAT_INEXACT_RESULT:
si.si_signo = SIGFPE;
si.si_sigval.sival_int = FPE_FLTRES;
break;
case STATUS_FLOAT_OVERFLOW:
si.si_signo = SIGFPE;
si.si_sigval.sival_int = FPE_FLTOVF;
break;
case STATUS_FLOAT_UNDERFLOW:
si.si_signo = SIGFPE;
si.si_sigval.sival_int = FPE_FLTUND;
break;
case STATUS_INTEGER_DIVIDE_BY_ZERO:
si.si_signo = SIGFPE;
si.si_sigval.sival_int = FPE_INTDIV;
break;
case STATUS_INTEGER_OVERFLOW:
sig = SIGFPE;
si.si_signo = SIGFPE;
si.si_sigval.sival_int = FPE_INTOVF;
break;
case STATUS_ILLEGAL_INSTRUCTION:
si.si_signo = SIGILL;
si.si_sigval.sival_int = ILL_ILLOPC;
break;
case STATUS_PRIVILEGED_INSTRUCTION:
si.si_signo = SIGILL;
si.si_sigval.sival_int = ILL_PRVOPC;
break;
case STATUS_NONCONTINUABLE_EXCEPTION:
sig = SIGILL;
si.si_signo = SIGILL;
si.si_sigval.sival_int = ILL_ILLADR;
break;
case STATUS_TIMEOUT:
sig = SIGALRM;
si.si_signo = SIGALRM;
si.si_sigval.sival_int = 0;
break;
case STATUS_ACCESS_VIOLATION:
@ -453,11 +479,13 @@ handle_exceptions (EXCEPTION_RECORD *e0, void *frame, CONTEXT *in0, void *)
case STATUS_NO_MEMORY:
case STATUS_INVALID_DISPOSITION:
case STATUS_STACK_OVERFLOW:
sig = SIGSEGV;
si.si_signo = SIGSEGV;
si.si_sigval.sival_int = SEGV_MAPERR;
break;
case STATUS_CONTROL_C_EXIT:
sig = SIGINT;
si.si_signo = SIGINT;
si.si_sigval.sival_int = 0;
break;
case STATUS_INVALID_HANDLE:
@ -476,13 +504,14 @@ handle_exceptions (EXCEPTION_RECORD *e0, void *frame, CONTEXT *in0, void *)
}
debug_printf ("In cygwin_except_handler exc %p at %p sp %p", e.ExceptionCode, in.Eip, in.Esp);
debug_printf ("In cygwin_except_handler sig = %d at %p", sig, in.Eip);
debug_printf ("In cygwin_except_handler sig = %d at %p", si.si_signo, in.Eip);
if (global_sigs[sig].sa_mask & SIGTOMASK (sig))
syscall_printf ("signal %d, masked %p", sig, global_sigs[sig].sa_mask);
if (global_sigs[si.si_signo].sa_mask & SIGTOMASK (si.si_signo))
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[sig].sa_handler);
global_sigs[si.si_signo].sa_handler);
DWORD *ebp = (DWORD *)in.Esp;
for (DWORD *bpend = (DWORD *) __builtin_frame_address (0); ebp > bpend; ebp--)
@ -494,23 +523,18 @@ handle_exceptions (EXCEPTION_RECORD *e0, void *frame, CONTEXT *in0, void *)
if (!myself->progname[0]
|| GetCurrentThreadId () == sigtid
|| (void *) global_sigs[sig].sa_handler == (void *) SIG_DFL
|| (void *) global_sigs[sig].sa_handler == (void *) SIG_IGN
|| (void *) global_sigs[sig].sa_handler == (void *) SIG_ERR)
|| (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 (1)
{
for (int i = 0; status_info[i].name; i++)
{
if (status_info[i].code == e.ExceptionCode)
{
if (!myself->ppid_handle)
system_printf ("Exception: %s", status_info[i].name);
break;
}
}
}
for (int i = 0; status_info[i].name; i++)
if (status_info[i].code == e.ExceptionCode)
{
if (!myself->ppid_handle)
system_printf ("Exception: %s", status_info[i].name);
break;
}
/* Another exception could happen while tracing or while exiting.
Only do this once. */
@ -529,11 +553,14 @@ handle_exceptions (EXCEPTION_RECORD *e0, void *frame, CONTEXT *in0, void *)
stackdump ((DWORD) ebp, 0, 1);
}
signal_exit (0x80 | sig); // Flag signal + core dump
signal_exit (0x80 | si.si_signo); // Flag signal + core dump
}
si.si_addr = ebp;
si.si_code = SI_KERNEL;
si.si_errno = si.si_pid = si.si_uid = 0;
_my_tls.push ((__stack_t) ebp, true);
sig_send (NULL, sig, &_my_tls); // Signal myself
sig_send (NULL, si, &_my_tls); // Signal myself
return 1;
}
#endif /* __i386__ */
@ -605,7 +632,14 @@ sig_handle_tty_stop (int sig)
{
pinfo parent (myself->ppid);
if (ISSTATE (parent, PID_NOCLDSTOP))
sig_send (parent, SIGCHLD);
{
siginfo_t si;
si.si_signo = SIGCHLD;
si.si_code = SI_KERNEL;
si.si_sigval.sival_int = CLD_STOPPED;
si.si_errno = si.si_pid = si.si_uid = si.si_errno = 0;
sig_send (parent, si);
}
}
sigproc_printf ("process %d stopped by signal %d, myself->ppid_handle %p",
myself->pid, sig, myself->ppid_handle);
@ -814,8 +848,8 @@ ctrl_c_handler (DWORD type)
{
if (type == CTRL_CLOSE_EVENT)
{
saw_close = true;
sig_send (NULL, SIGHUP);
saw_close = true;
return FALSE;
}
if (!saw_close && type == CTRL_LOGOFF_EVENT)
@ -849,7 +883,7 @@ ctrl_c_handler (DWORD type)
a CTRL_C_EVENT or CTRL_BREAK_EVENT. */
{
t->last_ctrl_c = GetTickCount ();
kill (-myself->pid, SIGINT);
killsys (-myself->pid, SIGINT);
t->last_ctrl_c = GetTickCount ();
return TRUE;
}
@ -884,9 +918,9 @@ set_signal_mask (sigset_t newmask, sigset_t oldmask)
}
int __stdcall
sig_handle (int sig, sigset_t mask, int pid, _threadinfo *tls)
sigpacket::process ()
{
if (sig == SIGCONT)
if (si.si_signo == SIGCONT)
{
DWORD stopped = myself->process_state & PID_STOPPED;
myself->stopsig = 0;
@ -901,41 +935,56 @@ sig_handle (int sig, sigset_t mask, int pid, _threadinfo *tls)
}
int rc = 1;
bool insigwait_mask = tls ? sigismember (&tls->sigwait_mask, sig) : false;
bool special_case = ISSTATE (myself, PID_STOPPED) || main_vfork->pid;
bool masked = sigismember (&mask, sig);
if (sig != SIGKILL && sig != SIGSTOP
&& (special_case || main_vfork->pid || masked || insigwait_mask
|| (tls && sigismember (&tls->sigmask, sig))))
sigproc_printf ("signal %d processing", si.si_signo);
struct sigaction thissig = global_sigs[si.si_signo];
myself->rusage_self.ru_nsignals++;
if (si.si_signo == SIGKILL)
goto exit_sig;
if ( si.si_signo == SIGSTOP)
{
sigproc_printf ("signal %d blocked", sig);
if ((!special_case && !masked)
&& (insigwait_mask || (tls = _threadinfo::find_tls (sig)) != NULL))
goto thread_specific;
sig_clear (SIGCONT);
goto stop;
}
bool masked;
bool special_case;
bool insigwait_mask;
insigwait_mask = masked = false;
if (special_case = (main_vfork->pid || ISSTATE (myself, PID_STOPPED)))
/* 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)))
insigwait_mask = true;
else if (!(masked = sigismember (mask, si.si_signo)) && tls)
masked = sigismember (&tls->sigmask, si.si_signo);
if (insigwait_mask)
goto thread_specific;
if (!tls)
tls = _main_tls;
if (special_case || masked)
{
sigproc_printf ("signal %d blocked", si.si_signo);
rc = -1;
goto done;
}
/* Clear pending SIGCONT on stop signals */
if (sig == SIGSTOP || sig == SIGTSTP || sig == SIGTTIN || sig == SIGTTOU)
sig_clear (SIGCONT);
sigproc_printf ("signal %d processing", sig);
struct sigaction thissig = global_sigs[sig];
void *handler;
handler = (void *) thissig.sa_handler;
myself->rusage_self.ru_nsignals++;
if (sig == SIGKILL)
goto exit_sig;
if (sig == SIGSTOP)
goto stop;
/* Clear pending SIGCONT on stop signals */
if (si.si_signo == SIGTSTP || si.si_signo == SIGTTIN || si.si_signo == SIGTTOU)
sig_clear (SIGCONT);
#if 0
char sigmsg[24];
__small_sprintf (sigmsg, "cygwin: signal %d\n", sig);
__small_sprintf (sigmsg, "cygwin: signal %d\n", si.si_signo);
OutputDebugString (sigmsg);
#endif
@ -943,14 +992,14 @@ sig_handle (int sig, sigset_t mask, int pid, _threadinfo *tls)
{
if (insigwait_mask)
goto thread_specific;
if (sig == SIGCHLD || sig == SIGIO || sig == SIGCONT || sig == SIGWINCH
|| sig == SIGURG)
if (si.si_signo == SIGCHLD || si.si_signo == SIGIO || si.si_signo == SIGCONT || si.si_signo == SIGWINCH
|| si.si_signo == SIGURG)
{
sigproc_printf ("default signal %d ignored", sig);
sigproc_printf ("default signal %d ignored", si.si_signo);
goto done;
}
if (sig == SIGTSTP || sig == SIGTTIN || sig == SIGTTOU)
if (si.si_signo == SIGTSTP || si.si_signo == SIGTTIN || si.si_signo == SIGTTOU)
goto stop;
goto exit_sig;
@ -958,7 +1007,7 @@ sig_handle (int sig, sigset_t mask, int pid, _threadinfo *tls)
if (handler == (void *) SIG_IGN)
{
sigproc_printf ("signal %d ignored", sig);
sigproc_printf ("signal %d ignored", si.si_signo);
goto done;
}
@ -973,34 +1022,38 @@ stop:
goto done;
handler = (void *) sig_handle_tty_stop;
thissig = global_sigs[SIGSTOP];
goto dosig1;
dosig:
tls->set_siginfo (this);
dosig1:
/* Dispatch to the appropriate function. */
sigproc_printf ("signal %d, about to call %p", sig, handler);
rc = setup_handler (sig, handler, thissig, tls ?: _main_tls);
sigproc_printf ("signal %d, about to call %p", si.si_signo, handler);
rc = setup_handler (si.si_signo, handler, thissig, tls);
done:
sigproc_printf ("returning %d", rc);
return rc;
thread_specific:
tls->sig = sig;
tls->sig = si.si_signo;
tls->set_siginfo (this);
sigproc_printf ("releasing sigwait for thread");
SetEvent (tls->event);
goto done;
exit_sig:
if (sig == SIGQUIT || sig == SIGABRT)
if (si.si_signo == SIGQUIT || si.si_signo == SIGABRT)
{
CONTEXT c;
c.ContextFlags = CONTEXT_FULL;
GetThreadContext (hMainThread, &c);
if (!try_to_debug ())
stackdump (c.Ebp, 1, 1);
sig |= 0x80;
si.si_signo |= 0x80;
}
sigproc_printf ("signal %d, about to call do_exit", sig);
signal_exit (sig);
sigproc_printf ("signal %d, about to call do_exit", si.si_signo);
signal_exit (si.si_signo);
/* Never returns */
}