From f6936c48f382a12b7b67fda40352b8e377662743 Mon Sep 17 00:00:00 2001 From: Christopher Faylor Date: Mon, 19 Jan 2004 05:46:54 +0000 Subject: * 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. --- winsup/cygwin/exceptions.cc | 193 ++++++++++++++++++++++++++++---------------- 1 file changed, 123 insertions(+), 70 deletions(-) (limited to 'winsup/cygwin/exceptions.cc') diff --git a/winsup/cygwin/exceptions.cc b/winsup/cygwin/exceptions.cc index 597c58e47..1e9745b22 100644 --- a/winsup/cygwin/exceptions.cc +++ b/winsup/cygwin/exceptions.cc @@ -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 */ } -- cgit v1.2.3