diff options
author | Corinna Vinschen <corinna@vinschen.de> | 2014-11-28 20:46:13 +0000 |
---|---|---|
committer | Corinna Vinschen <corinna@vinschen.de> | 2014-11-28 20:46:13 +0000 |
commit | 26158dc3e9c20fc0488944f0c3eefdc19255e7da (patch) | |
tree | 93f7cb9eab294721a54e3892e5e81be7791c0544 /winsup/cygwin/exceptions.cc | |
parent | c2f50c4099b5b3db7dca5797bde8c5886d999c36 (diff) | |
download | cygnal-26158dc3e9c20fc0488944f0c3eefdc19255e7da.tar.gz cygnal-26158dc3e9c20fc0488944f0c3eefdc19255e7da.tar.bz2 cygnal-26158dc3e9c20fc0488944f0c3eefdc19255e7da.zip |
* cygheap.cc (init_cygheap::init_tls_list): Accommodate threadlist
having a new type threadlist_t *. Convert commented out code into an
#if 0. Create thread mutex. Explain why.
(init_cygheap::remove_tls): Drop timeout value. Always wait infinitely
for tls_sentry. Return mutex HANDLE of just deleted threadlist entry.
(init_cygheap::find_tls): New implementation taking tls pointer as
search parameter. Return threadlist_t *.
(init_cygheap::find_tls): Return threadlist_t *. Define ix as auto
variable. Drop exception handling since crash must be made impossible
due to correct synchronization. Return with locked mutex.
* cygheap.h (struct threadlist_t): Define.
(struct init_cygheap): Convert threadlist to threadlist_t type.
(init_cygheap::remove_tls): Align declaration to above change.
(init_cygheap::find_tls): Ditto.
(init_cygheap::unlock_tls): Define.
* cygtls.cc (_cygtls::remove): Unlock and close mutex when finishing.
* exceptions.cc (sigpacket::process): Lock _cygtls area of thread before
accessing it.
* fhandler_termios.cc (fhandler_termios::bg_check): Ditto.
* sigproc.cc (sig_send): Ditto.
* thread.cc (pthread::exit): Ditto. Add comment.
(pthread::cancel): Ditto.
Diffstat (limited to 'winsup/cygwin/exceptions.cc')
-rw-r--r-- | winsup/cygwin/exceptions.cc | 62 |
1 files changed, 46 insertions, 16 deletions
diff --git a/winsup/cygwin/exceptions.cc b/winsup/cygwin/exceptions.cc index 4e9c77036..c16b073c6 100644 --- a/winsup/cygwin/exceptions.cc +++ b/winsup/cygwin/exceptions.cc @@ -1299,6 +1299,9 @@ sigpacket::process () struct sigaction& thissig = global_sigs[si.si_signo]; void *handler = have_execed ? NULL : (void *) thissig.sa_handler; + threadlist_t *tl_entry = NULL; + _cygtls *tls = NULL; + /* Don't try to send signals if we're just starting up since signal masks may not be available. */ if (!cygwin_finished_initializing) @@ -1311,12 +1314,19 @@ sigpacket::process () myself->rusage_self.ru_nsignals++; - _cygtls *tls; if (si.si_signo == SIGCONT) - _main_tls->handle_SIGCONT (); + { + tl_entry = cygheap->find_tls (_main_tls); + _main_tls->handle_SIGCONT (); + cygheap->unlock_tls (tl_entry); + } + /* SIGKILL is special. It always goes through. */ if (si.si_signo == SIGKILL) - tls = _main_tls; /* SIGKILL is special. It always goes through. */ + { + tl_entry = cygheap->find_tls (_main_tls); + tls = _main_tls; + } else if (ISSTATE (myself, PID_STOPPED)) { rc = -1; /* Don't send signals when stopped */ @@ -1324,18 +1334,29 @@ sigpacket::process () } else if (!sigtls) { - tls = cygheap->find_tls (si.si_signo, issig_wait); - sigproc_printf ("using tls %p", tls); + tl_entry = cygheap->find_tls (si.si_signo, issig_wait); + if (tl_entry) + { + tls = tl_entry->thread; + sigproc_printf ("using tls %p", tls); + } } else { - tls = sigtls; - if (sigismember (&tls->sigwait_mask, si.si_signo)) - issig_wait = true; - else if (!sigismember (&tls->sigmask, si.si_signo)) - issig_wait = false; - else - tls = NULL; + tl_entry = cygheap->find_tls (sigtls); + if (tl_entry) + { + tls = tl_entry->thread; + if (sigismember (&tls->sigwait_mask, si.si_signo)) + issig_wait = true; + else if (!sigismember (&tls->sigmask, si.si_signo)) + issig_wait = false; + else + { + cygheap->unlock_tls (tl_entry); + tls = NULL; + } + } } /* !tls means no threads available to catch a signal. */ @@ -1371,19 +1392,22 @@ sigpacket::process () } /* Clear pending SIGCONT on stop signals */ - if (si.si_signo == SIGTSTP || si.si_signo == SIGTTIN || si.si_signo == SIGTTOU) + if (si.si_signo == SIGTSTP || si.si_signo == SIGTTIN + || si.si_signo == SIGTTOU) sig_clear (SIGCONT); if (handler == (void *) SIG_DFL) { - if (si.si_signo == SIGCHLD || si.si_signo == SIGIO || si.si_signo == SIGCONT || si.si_signo == SIGWINCH + if (si.si_signo == SIGCHLD || si.si_signo == SIGIO + || si.si_signo == SIGCONT || si.si_signo == SIGWINCH || si.si_signo == SIGURG) { sigproc_printf ("signal %d default is currently ignore", si.si_signo); goto done; } - if (si.si_signo == SIGTSTP || si.si_signo == SIGTTIN || si.si_signo == SIGTTOU) + if (si.si_signo == SIGTSTP || si.si_signo == SIGTTIN + || si.si_signo == SIGTTOU) goto stop; goto exit_sig; @@ -1395,7 +1419,12 @@ sigpacket::process () goto dosig; stop: - tls = _main_tls; + if (tls != _main_tls) + { + cygheap->unlock_tls (tl_entry); + tl_entry = cygheap->find_tls (_main_tls); + tls = _main_tls; + } handler = (void *) sig_handle_tty_stop; thissig = global_sigs[SIGSTOP]; goto dosig; @@ -1415,6 +1444,7 @@ dosig: rc = setup_handler (handler, thissig, tls); done: + cygheap->unlock_tls (tl_entry); sigproc_printf ("returning %d", rc); return rc; |