diff options
Diffstat (limited to 'winsup/cygwin/sigproc.cc')
-rw-r--r-- | winsup/cygwin/sigproc.cc | 98 |
1 files changed, 43 insertions, 55 deletions
diff --git a/winsup/cygwin/sigproc.cc b/winsup/cygwin/sigproc.cc index e585877b9..55c5bbac9 100644 --- a/winsup/cygwin/sigproc.cc +++ b/winsup/cygwin/sigproc.cc @@ -44,8 +44,6 @@ char NO_COPY myself_nowait_dummy[1] = {'0'};// Flag to sig_send that signal goes #define Static static NO_COPY -Static HANDLE sig_hold; // Used to stop signal processing -Static bool sigheld; // True if holding signals Static int nprocs; // Number of deceased children Static char cprocs[(NPROCS + 1) * sizeof (pinfo)];// All my children info @@ -171,7 +169,7 @@ mychild (int pid) /* Handle all subprocess requests */ int __reg2 -proc_subproc (DWORD what, DWORD val) +proc_subproc (DWORD what, uintptr_t val) { int rc = 1; int potential_match; @@ -449,7 +447,16 @@ exit_thread (DWORD res) # undef ExitThread sigfillset (&_my_tls.sigmask); /* No signals wanted */ lock_process for_now; /* May block indefinitely when exiting. */ - if (exit_state) + /* ES_EXIT_STARTING indicates that exit is in progress. After setting + exit_state to ES_EXIT_STARTING, the global dtors are running first, + then the exit state is set to the next level in do_exit. We must not + block the thread exit while the global dtors are running, because + one of them might have called pthread_join, which is perfectly valid + for a global C++ destructor. + FIXME: Do we need another state between ES_EXIT_STARTING and + ES_SIGNAL_EXIT to narrow the gap in which the thread exit + is still valid? */ + if (exit_state > ES_EXIT_STARTING) { for_now.release (); Sleep (INFINITE); @@ -478,24 +485,6 @@ exit_thread (DWORD res) int __reg3 sig_send (_pinfo *p, int sig, _cygtls *tid) { - if (sig == __SIGHOLD) - sigheld = true; - else if (!sigheld) - /* nothing */; - else if (sig == __SIGFLUSH || sig == __SIGFLUSHFAST) - return 0; - else if (sig == __SIGNOHOLD) - { - SetEvent (sig_hold); - sigheld = false; - } - else if (&_my_tls == _main_tls) - { -#ifdef DEBUGGING - system_printf ("signal %d sent to %p while signals are on hold", sig, p); -#endif - return -1; - } siginfo_t si = {}; si.si_signo = sig; si.si_code = SI_KERNEL; @@ -991,7 +980,7 @@ child_info::sync (pid_t pid, HANDLE& hProcess, DWORD howlong) hProcess = NULL; } } - sigproc_printf ("pid %u, WFMO returned %d, exit_code %p, res %d", pid, x, + sigproc_printf ("pid %u, WFMO returned %d, exit_code %y, res %d", pid, x, exit_code, res); } return res; @@ -1002,7 +991,7 @@ child_info::proc_retry (HANDLE h) { if (!exit_code) return EXITCODE_OK; - sigproc_printf ("exit_code %p", exit_code); + sigproc_printf ("exit_code %y", exit_code); switch (exit_code) { case STILL_ACTIVE: /* shouldn't happen */ @@ -1226,7 +1215,7 @@ static void WINAPI wait_sig (VOID *) { _sig_tls = &_my_tls; - sig_hold = CreateEvent (&sec_none_nih, FALSE, FALSE, NULL); + bool sig_held = false; sigproc_printf ("entering ReadFile loop, my_readsig %p, my_sendsig %p", my_readsig, my_sendsig); @@ -1275,33 +1264,7 @@ wait_sig (VOID *) *pack.mask |= bit; break; case __SIGHOLD: - goto loop; - break; - default: - if (pack.si.si_signo < 0) - sig_clear (-pack.si.si_signo); - else - sigq.add (pack); - case __SIGNOHOLD: - case __SIGFLUSH: - case __SIGFLUSHFAST: - { - sigpacket *qnext; - /* Check the queue for signals. There will always be at least one - thing on the queue if this was a valid signal. */ - while ((qnext = q->next)) - { - if (qnext->si.si_signo && qnext->process () <= 0) - q = q->next; - else - { - q->next = qnext->next; - qnext->si.si_signo = 0; - } - } - if (pack.si.si_signo == SIGCHLD) - clearwait = true; - } + sig_held = true; break; case __SIGSETPGRP: init_console_handler (true); @@ -1328,16 +1291,41 @@ wait_sig (VOID *) } } break; + default: + if (pack.si.si_signo < 0) + sig_clear (-pack.si.si_signo); + else + sigq.add (pack); + case __SIGNOHOLD: + sig_held = false; + case __SIGFLUSH: + case __SIGFLUSHFAST: + if (!sig_held) + { + sigpacket *qnext; + /* Check the queue for signals. There will always be at least one + thing on the queue if this was a valid signal. */ + while ((qnext = q->next)) + { + if (qnext->si.si_signo && qnext->process () <= 0) + q = q->next; + else + { + q->next = qnext->next; + qnext->si.si_signo = 0; + } + } + if (pack.si.si_signo == SIGCHLD) + clearwait = true; + } + break; } if (clearwait && !have_execed) proc_subproc (PROC_CLEARWAIT, 0); - loop: if (pack.wakeup) { sigproc_printf ("signalling pack.wakeup %p", pack.wakeup); SetEvent (pack.wakeup); } - if (pack.si.si_signo == __SIGHOLD) - WaitForSingleObject (sig_hold, INFINITE); } } |