diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index fc37e0d12..ba23ea6d0 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,26 @@ +2011-12-04 Christopher Faylor + + * exceptions.cc (exception::handle): Drop abbreviation for "exception" + since I never remember what it stands for. + (sig_handle_tty_stop): Remove obsolete call to sig_handle_tty_stop. + (_cygtls::call_signal_handler): Rework to grab signal information from + _main_tls if none is set for _my_tls. Try harder to keep thread + locked. + (reset_signal_arrived): Delete. + * fhandler.cc (fhandler_base_overlapped::wait_overlapped): Use new + cygWFMO call to wait for an event + standard cygwin stuff. Modify + debug output to acccomodate new function. + * fhandler_console.cc (fhandler_console::read): Replace + WaitForMultipleObjects with cygWFMO. + * fhandler_socket.cc (get_inet_addr): Add comment. + * gendef (_sigdelayed): Remove call to reset_signal_arrived. + * sigproc.cc (_cygtls::signal_exit): Don't close my_readsig here unless + we're in the signal thread. + (create_signal_arrived): Create signal_arrived as auto-reset so that only + one thread is woken when a signal arrives. + * sigproc.h (cygWFMO): New function. + (reset_signal_arrived): Delete declaration. + 2011-12-03 Christopher Faylor * mmap.cc (mlock): Add standard syscall return value debugging output. diff --git a/winsup/cygwin/exceptions.cc b/winsup/cygwin/exceptions.cc index 5e6137ffd..c62b81662 100644 --- a/winsup/cygwin/exceptions.cc +++ b/winsup/cygwin/exceptions.cc @@ -600,7 +600,7 @@ exception::handle (EXCEPTION_RECORD *e, exception_list *frame, CONTEXT *in, void return 1; } - debug_printf ("In cygwin_except_handler exc %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); bool masked = !!(me.sigmask & SIGTOMASK (si.si_signo)); @@ -755,7 +755,6 @@ sig_handle_tty_stop (int sig) { case WAIT_OBJECT_0: case WAIT_OBJECT_0 + 1: - reset_signal_arrived (); myself->stopsig = SIGCONT; myself->alert_parent (SIGCONT); break; @@ -1325,25 +1324,42 @@ events_terminate () int _cygtls::call_signal_handler () { - int this_sa_flags = 0; - /* Call signal handler. */ - while (sig && func) + int this_sa_flags = SA_RESTART; + while (1) { lock (); + if (sig) + pop (); + else if (this != _main_tls) + { + _main_tls->lock (); + if (_main_tls->sig) + { + sig = _main_tls->sig; + sa_flags = _main_tls->sa_flags; + func = _main_tls->func; + infodata = _main_tls->infodata; + _main_tls->pop (); + _main_tls->sig = 0; + + } + _main_tls->unlock (); + } + if (!sig) + break; + this_sa_flags = sa_flags; int thissig = sig; void (*thisfunc) (int) = func; - pop (); - reset_signal_arrived (); sigset_t this_oldmask = set_process_mask_delta (); int this_errno = saved_errno; sig = 0; unlock (); // make sure synchronized - incyg = 0; if (!(this_sa_flags & SA_SIGINFO)) { void (*sigfunc) (int) = thisfunc; + incyg = false; sigfunc (thissig); } else @@ -1351,27 +1367,19 @@ _cygtls::call_signal_handler () siginfo_t thissi = infodata; void (*sigact) (int, siginfo_t *, void *) = (void (*) (int, siginfo_t *, void *)) thisfunc; /* no ucontext_t information provided yet */ + incyg = false; sigact (thissig, &thissi, NULL); } - incyg = 1; + incyg = true; set_signal_mask (this_oldmask, _my_tls.sigmask); if (this_errno >= 0) set_errno (this_errno); } + unlock (); return this_sa_flags & SA_RESTART; } -extern "C" void __stdcall -reset_signal_arrived () -{ - // NEEDED? WaitForSingleObject (signal_arrived, 10); - ResetEvent (signal_arrived); - sigproc_printf ("reset signal_arrived"); - if (_my_tls.stackptr > _my_tls.stack) - debug_printf ("stackptr[-1] %p", _my_tls.stackptr[-1]); -} - void _cygtls::copy_context (CONTEXT *c) { diff --git a/winsup/cygwin/fhandler.cc b/winsup/cygwin/fhandler.cc index 6049036b5..a29b1f235 100644 --- a/winsup/cygwin/fhandler.cc +++ b/winsup/cygwin/fhandler.cc @@ -1925,11 +1925,8 @@ fhandler_base_overlapped::wait_overlapped (bool inres, bool writing, DWORD *byte } if (res == overlapped_unknown) { - HANDLE w4[3] = { get_overlapped ()->hEvent, signal_arrived, - pthread::get_cancel_event () }; - DWORD n = w4[2] ? 3 : 2; HANDLE h = writing ? get_output_handle () : get_handle (); - DWORD wfres = WaitForMultipleObjects (n, w4, false, INFINITE); + DWORD wfres = cygWFMO (1, INFINITE, get_overlapped ()->hEvent); /* Cancelling here to prevent races. It's possible that the I/O has completed already, in which case this is a no-op. Otherwise, WFMO returned because 1) This is a non-blocking call, 2) a signal @@ -1960,7 +1957,7 @@ fhandler_base_overlapped::wait_overlapped (bool inres, bool writing, DWORD *byte pthread::static_cancel_self (); /* never returns */ else { - debug_printf ("GetOverLappedResult failed, h %p, bytes %u, w4: %p, %p, %p %E", h, *bytes, w4[0], w4[1], w4[2]); + debug_printf ("GetOverLappedResult failed, h %p, bytes %u, %E", h, *bytes); res = overlapped_error; } } diff --git a/winsup/cygwin/fhandler_console.cc b/winsup/cygwin/fhandler_console.cc index 0e9717bd1..e8a8d6a08 100644 --- a/winsup/cygwin/fhandler_console.cc +++ b/winsup/cygwin/fhandler_console.cc @@ -333,8 +333,6 @@ fhandler_console::read (void *pv, size_t& buflen) return; } - HANDLE w4[3] = { h, signal_arrived, pthread::get_cancel_event () }; - DWORD nwait = w4[2] ? 3 : 2; DWORD timeout = is_nonblocking () ? 0 : INFINITE; char tmp[60]; @@ -350,7 +348,7 @@ fhandler_console::read (void *pv, size_t& buflen) set_cursor_maybe (); /* to make cursor appear on the screen immediately */ restart: - switch (WaitForMultipleObjects (nwait, w4, FALSE, timeout)) + switch (cygWFMO (1, timeout, h)) { case WAIT_OBJECT_0: break; diff --git a/winsup/cygwin/fhandler_socket.cc b/winsup/cygwin/fhandler_socket.cc index fff1083c3..17d98dc38 100644 --- a/winsup/cygwin/fhandler_socket.cc +++ b/winsup/cygwin/fhandler_socket.cc @@ -127,6 +127,8 @@ get_inet_addr (const struct sockaddr *in, int inlen, some greedy Win32 application. Therefore we should never wait endlessly without checking for signals and thread cancel event. */ pthread_testcancel (); + /* Using IsEventSignalled like this is racy since another thread could + be waiting for signal_arrived. */ if (IsEventSignalled (signal_arrived) && !_my_tls.call_signal_handler ()) { diff --git a/winsup/cygwin/gendef b/winsup/cygwin/gendef index e1fa0d9e4..0cd27341f 100755 --- a/winsup/cygwin/gendef +++ b/winsup/cygwin/gendef @@ -232,7 +232,6 @@ _sigdelayed: pushl %eax # siginfo pushl $tls::sig(%ebx) # signal number - call _reset_signal_arrived\@0 pushl \$_sigreturn # where to return pushl $tls::func(%ebx) # user-supplied signal func cmpl \$0,$tls::threadkill(%ebx)#pthread_kill signal? diff --git a/winsup/cygwin/sigproc.cc b/winsup/cygwin/sigproc.cc index eef082f6f..1770b4f21 100644 --- a/winsup/cygwin/sigproc.cc +++ b/winsup/cygwin/sigproc.cc @@ -368,8 +368,18 @@ _cygtls::signal_exit (int rc) { extern void stackdump (DWORD, int, bool); + HANDLE myss = my_sendsig; my_sendsig = NULL; /* Make no_signals_allowed return true */ - ForceCloseHandle (my_readsig); /* Stop any currently executing sig_sends */ + if (&_my_tls == _sig_tls) + ForceCloseHandle (my_readsig); /* Stop any currently executing sig_sends */ + else + { + sigpacket sp = {}; + sp.si.si_signo = __SIGEXIT; + DWORD len; + WriteFile (myss, &sp, sizeof (sp), &len, NULL); + } + SetEvent (signal_arrived); /* Avoid potential deadlock with proc_lock */ if (rc == SIGQUIT || rc == SIGABRT) @@ -493,7 +503,7 @@ create_signal_arrived () return; /* local event signaled when main thread has been dispatched to a signal handler function. */ - signal_arrived = CreateEvent (&sec_none_nih, TRUE, FALSE, NULL); + signal_arrived = CreateEvent (&sec_none_nih, false, false, NULL); ProtectHandle (signal_arrived); } diff --git a/winsup/cygwin/sigproc.h b/winsup/cygwin/sigproc.h index b6f17a612..086466b6f 100644 --- a/winsup/cygwin/sigproc.h +++ b/winsup/cygwin/sigproc.h @@ -59,6 +59,21 @@ struct sigpacket }; extern HANDLE signal_arrived; + +static inline +DWORD cygWFMO (DWORD n, DWORD howlong, ...) +{ + va_list ap; + va_start (ap, howlong); + HANDLE w4[n + 2]; + va_start (ap, howlong); + unsigned i; + for (i = 0; i < n; i++) + w4[i] = va_arg (ap, HANDLE); + w4[i++] = signal_arrived; + w4[i++] = pthread::get_cancel_event (); + return WaitForMultipleObjects (n, w4, FALSE, howlong); +} extern HANDLE sigCONT; void __stdcall sig_dispatch_pending (bool fast = false); @@ -69,7 +84,6 @@ int __stdcall handle_sigprocmask (int sig, const sigset_t *set, sigset_t *oldset, sigset_t& opmask) __attribute__ ((regparm (3))); -extern "C" void __stdcall reset_signal_arrived (); void __stdcall sig_clear (int) __attribute__ ((regparm (1))); void __stdcall sig_set_pending (int) __attribute__ ((regparm (1))); int __stdcall handle_sigsuspend (sigset_t);