* DevNotes: Add entry cgf-000013.
* cygserver_ipc.h (ipc_set_proc_info): Use _cygtls::ipc_set_proc_info to set per-thread signal arrived value. * cygthread.cc (cygthread::detach): Use per-thread signal_arrived via set_thread_waiting. * fork.cc (_cygtls::fixup_after_fork): Clear signal_arrived. (_cygtls::remove): Close any signal_arrived handle when thread exists. (_cygtls::find_tls): Remove unneeded function. * cygtls.h: Update copyright. (class _cygtls): Reorganize to help avoid rebuilding newlib when structure changes. (_cygtls::event): Delete. (_cygtls::threadkill): Ditto. (_cygtls::signal_waiting): Declare new bool. (_cygtls::find_tls): Delete declaration. (_cygtls::set_threadkill): Ditto. (_cygtls::reset_threadkill): Ditto. (_cygtls::set_signal_arrived): Declare new function. (class set_thread_waiting): Declare new class. * cygwait.cc (cw_nowait_storage): Define. (cygwait): Set per-thread signal_arrived via set_thread_waiting. Don't special-case _main_tls. * cygwait.h (cw_nowait): Define. (cw_infinite): Ditto. (cygwait): Redefine pathological wait-only case. * dcrt0.cc (dll_crt0_0): Remove call to now-defunct events_init(). (dll_crt0_1): Remove call to now-defunct create_signal_arrived(). * exceptions.cc: Reflect set_signal_mask() argument reordering throughout. Remove signal mask synchronization throughout. (events_init): Delete definition. (mask_sync): Delete now-unneeded mask synchronization. (set_signal_mask): Reverse order of arguments to "standard" to, from layout. Rename "newmask" argument to "setmask". Remove debugging. (sig_handle_tty_stop): Use cancelable_wait rather than WFMO. (_cygtls::interrupt_setup): Don't treat "threadkill" events specially. Conditionally set signal_arrived depending on whether the thread has created it or not. (sigpacket::process): Reorganize to reflect thread-specific sending of signals which is more in line with the way it was actually supposed to work. * fhandler_socket.cc (get_inet_addr): Use cancelable_wait rather than IsEventSignalled to avoid potential race. (fhandler_socket::wait_for_events): Set signal_arrived event using set_thread_waiting(). (fhandler_socket::close): Use cygwait for the case of just waiting 10 ms for a signal. * fhandler_tape.cc (fhandler_dev_tape::_lock): Use cancelable_wait rather than WFMO. Redo switch/case tests accordingly. * fhandler_termios.cc (fhandler_termios::bg_check): Use cygwait for case of just waiting 0 ms for a potential signal. * fhandler_tty.cc (fhandler_pty_master::process_slave_output): Use cancelable_wait rather than WFSO. * fhandler_windows.cc (fhandler_windows::read): Set per-thread signal_arrived via set_thread_waiting(). * flock.cc (lf_setlock): Ditto. * select.cc (pselect): Ditto. Set per-thread signal_arrived using set_thread_waiting(). * gendef: Don't special case handling of _cygtls::sig for threads. * gentls_offsets: Use #pragma once in tlsoffsets.h. * ntdll.h: Use #pragma once. * poll.cc: Reflect set_signal_mask() argument reordering. * posix_ipc.cc (ipc_mutex_lock): Use cancelable_wait rather than WFMO. (ipc_cond_timedwait): Set perl-thread signal arrived using set_thread_waiting(). * security.h: Use #pragma once. * signal.cc (abort): Reflect set_signal_mask() argument reordering. (clock_nanosleep): Ditto. Change call to cancelable_wait to properly specify handling of cancel and interrupt. (sigwaitinfo): Remove handling of per-thread event in favor of per-thread signal_arrived. Use cancelable_wait rather than WFSO. * sigproc.cc (signal_arrived): Delete definition. (create_signal_arrived): Ditto. * sigproc.h (signal_arrived): Delete declaration. (set_signal_mask): Avoid defining as a "C" function. Don't conditionally declare. (create_signal_arrived): Delete declaration. * syscalls.cc (rename): Use cygwait() rather than WFSO. * thread.h (fast_mutex::lock): Use cw_infinite rather than LARGE_NULL. * wait.cc (wait4): Ditto. * thread.cc (pthread_mutex::lock): Ditto. (pthread::join): Ditto. (semaphore::_wait): Ditto. (pthread_kill): Remove set_threadkill() accommodation. * tlsoffsets.h: Regenerate.
This commit is contained in:
@ -19,8 +19,8 @@ details. */
|
||||
#include <syslog.h>
|
||||
#include <wchar.h>
|
||||
|
||||
#include "pinfo.h"
|
||||
#include "cygtls.h"
|
||||
#include "pinfo.h"
|
||||
#include "sigproc.h"
|
||||
#include "shared_info.h"
|
||||
#include "perprocess.h"
|
||||
@ -31,7 +31,6 @@ details. */
|
||||
#include "child_info.h"
|
||||
#include "ntdll.h"
|
||||
#include "exception.h"
|
||||
#include "cygwait.h"
|
||||
|
||||
#define CALL_HANDLER_RETRY_OUTER 10
|
||||
#define CALL_HANDLER_RETRY_INNER 10
|
||||
@ -47,7 +46,6 @@ static BOOL WINAPI ctrl_c_handler (DWORD);
|
||||
/* This is set to indicate that we have already exited. */
|
||||
|
||||
static NO_COPY int exit_already = 0;
|
||||
static muto NO_COPY mask_sync;
|
||||
|
||||
NO_COPY static struct
|
||||
{
|
||||
@ -710,11 +708,11 @@ handle_sigsuspend (sigset_t tempmask)
|
||||
{
|
||||
sigset_t oldmask = _my_tls.sigmask; // Remember for restoration
|
||||
|
||||
set_signal_mask (tempmask, _my_tls.sigmask);
|
||||
set_signal_mask (_my_tls.sigmask, tempmask);
|
||||
sigproc_printf ("oldmask %p, newmask %p", oldmask, tempmask);
|
||||
|
||||
pthread_testcancel ();
|
||||
cancelable_wait (signal_arrived, LARGE_NULL, cw_cancel | cw_cancel_self);
|
||||
cancelable_wait (NULL, cw_infinite, cw_cancel | cw_cancel_self | cw_sig_eintr);
|
||||
|
||||
set_sig_errno (EINTR); // Per POSIX
|
||||
|
||||
@ -747,8 +745,7 @@ sig_handle_tty_stop (int sig)
|
||||
sigproc_printf ("process %d stopped by signal %d", myself->pid, sig);
|
||||
HANDLE w4[2];
|
||||
w4[0] = sigCONT;
|
||||
w4[1] = signal_arrived;
|
||||
switch (WaitForMultipleObjects (2, w4, TRUE, INFINITE))
|
||||
switch (cancelable_wait (sigCONT, cw_infinite, cw_sig_eintr))
|
||||
{
|
||||
case WAIT_OBJECT_0:
|
||||
case WAIT_OBJECT_0 + 1:
|
||||
@ -804,20 +801,11 @@ _cygtls::interrupt_setup (int sig, void *handler, struct sigaction& siga)
|
||||
|
||||
this->sig = sig; // Should always be last thing set to avoid a race
|
||||
|
||||
if (!event)
|
||||
threadkill = false;
|
||||
else
|
||||
{
|
||||
HANDLE h = event;
|
||||
event = NULL;
|
||||
SetEvent (h);
|
||||
}
|
||||
if (signal_arrived)
|
||||
SetEvent (signal_arrived);
|
||||
|
||||
/* Clear any waiting threads prior to dispatching to handler function */
|
||||
int res = SetEvent (signal_arrived); // For an EINTR case
|
||||
proc_subproc (PROC_CLEARWAIT, 1);
|
||||
sigproc_printf ("armed signal_arrived %p, signal %d, res %d", signal_arrived,
|
||||
sig, res);
|
||||
sigproc_printf ("armed signal_arrived %p, signal %d", signal_arrived, sig);
|
||||
}
|
||||
|
||||
extern "C" void __stdcall
|
||||
@ -1021,7 +1009,7 @@ ctrl_c_handler (DWORD type)
|
||||
extern "C" void __stdcall
|
||||
set_process_mask (sigset_t newmask)
|
||||
{
|
||||
set_signal_mask (newmask, _my_tls.sigmask);
|
||||
set_signal_mask (_my_tls.sigmask, newmask);
|
||||
}
|
||||
|
||||
extern "C" int
|
||||
@ -1034,11 +1022,9 @@ sighold (int sig)
|
||||
syscall_printf ("signal %d out of range", sig);
|
||||
return -1;
|
||||
}
|
||||
mask_sync.acquire (INFINITE);
|
||||
sigset_t mask = _my_tls.sigmask;
|
||||
sigaddset (&mask, sig);
|
||||
set_signal_mask (mask, _my_tls.sigmask);
|
||||
mask_sync.release ();
|
||||
set_signal_mask (_my_tls.sigmask, mask);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1052,11 +1038,9 @@ sigrelse (int sig)
|
||||
syscall_printf ("signal %d out of range", sig);
|
||||
return -1;
|
||||
}
|
||||
mask_sync.acquire (INFINITE);
|
||||
sigset_t mask = _my_tls.sigmask;
|
||||
sigdelset (&mask, sig);
|
||||
set_signal_mask (mask, _my_tls.sigmask);
|
||||
mask_sync.release ();
|
||||
set_signal_mask (_my_tls.sigmask, mask);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1074,7 +1058,6 @@ sigset (int sig, _sig_func_ptr func)
|
||||
return (_sig_func_ptr) SIG_ERR;
|
||||
}
|
||||
|
||||
mask_sync.acquire (INFINITE);
|
||||
sigset_t mask = _my_tls.sigmask;
|
||||
/* If sig was in the signal mask return SIG_HOLD, otherwise return the
|
||||
previous disposition. */
|
||||
@ -1093,8 +1076,7 @@ sigset (int sig, _sig_func_ptr func)
|
||||
signal (sig, func);
|
||||
sigdelset (&mask, sig);
|
||||
}
|
||||
set_signal_mask (mask, _my_tls.sigmask);
|
||||
mask_sync.release ();
|
||||
set_signal_mask (_my_tls.sigmask, mask);
|
||||
return prev;
|
||||
}
|
||||
|
||||
@ -1109,7 +1091,6 @@ sigignore (int sig)
|
||||
extern "C" sigset_t
|
||||
set_process_mask_delta ()
|
||||
{
|
||||
mask_sync.acquire (INFINITE);
|
||||
sigset_t newmask, oldmask;
|
||||
|
||||
if (_my_tls.deltamask & SIG_NONMASKABLE)
|
||||
@ -1120,28 +1101,22 @@ set_process_mask_delta ()
|
||||
sigproc_printf ("oldmask %p, newmask %p, deltamask %p", oldmask, newmask,
|
||||
_my_tls.deltamask);
|
||||
_my_tls.sigmask = newmask;
|
||||
mask_sync.release ();
|
||||
return oldmask;
|
||||
}
|
||||
|
||||
/* Set the signal mask for this process.
|
||||
Note that some signals are unmaskable, as in UNIX. */
|
||||
extern "C" void __stdcall
|
||||
set_signal_mask (sigset_t newmask, sigset_t& oldmask)
|
||||
|
||||
void
|
||||
set_signal_mask (sigset_t& setmask, sigset_t newmask)
|
||||
{
|
||||
#ifdef CGF
|
||||
if (&_my_tls == _sig_tls)
|
||||
small_printf ("********* waiting in signal thread\n");
|
||||
#endif
|
||||
mask_sync.acquire (INFINITE);
|
||||
newmask &= ~SIG_NONMASKABLE;
|
||||
sigset_t mask_bits = oldmask & ~newmask;
|
||||
sigproc_printf ("oldmask %p, newmask %p, mask_bits %p", oldmask, newmask,
|
||||
sigset_t mask_bits = setmask & ~newmask;
|
||||
sigproc_printf ("setmask %p, newmask %p, mask_bits %p", setmask, newmask,
|
||||
mask_bits);
|
||||
oldmask = newmask;
|
||||
setmask = newmask;
|
||||
if (mask_bits)
|
||||
sig_dispatch_pending (true);
|
||||
mask_sync.release ();
|
||||
}
|
||||
|
||||
int __stdcall
|
||||
@ -1184,17 +1159,23 @@ sigpacket::process ()
|
||||
|
||||
myself->rusage_self.ru_nsignals++;
|
||||
|
||||
bool masked;
|
||||
void *handler;
|
||||
if (!have_execed || (void *) thissig.sa_handler == (void *) SIG_IGN)
|
||||
handler = (void *) thissig.sa_handler;
|
||||
else if (tls)
|
||||
return 1;
|
||||
else
|
||||
void *handler = (void *) thissig.sa_handler;
|
||||
if (handler == SIG_IGN)
|
||||
{
|
||||
sigproc_printf ("signal %d ignored", si.si_signo);
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (have_execed)
|
||||
handler = NULL;
|
||||
|
||||
_cygtls *use_tls = tls ?: _main_tls;
|
||||
sigproc_printf ("tls %p, use_tls %p", tls, use_tls);
|
||||
if (tls)
|
||||
sigproc_printf ("using tls %p", tls);
|
||||
else
|
||||
{
|
||||
tls = _main_tls;
|
||||
sigproc_printf ("using main tls %p", _main_tls);
|
||||
}
|
||||
|
||||
if (si.si_signo == SIGKILL)
|
||||
goto exit_sig;
|
||||
@ -1204,30 +1185,12 @@ sigpacket::process ()
|
||||
goto stop;
|
||||
}
|
||||
|
||||
bool insigwait_mask;
|
||||
if ((masked = ISSTATE (myself, PID_STOPPED)))
|
||||
insigwait_mask = false;
|
||||
else if (tls)
|
||||
insigwait_mask = sigismember (&tls->sigwait_mask, si.si_signo);
|
||||
else if (!(tls = _cygtls::find_tls (si.si_signo)))
|
||||
insigwait_mask = false;
|
||||
else
|
||||
if (sigismember (&tls->sigwait_mask, si.si_signo))
|
||||
{
|
||||
use_tls = tls;
|
||||
insigwait_mask = true;
|
||||
tls->sigwait_mask = 0;
|
||||
goto dosig;
|
||||
}
|
||||
|
||||
if (insigwait_mask)
|
||||
goto thread_specific;
|
||||
|
||||
if (masked)
|
||||
/* nothing to do */;
|
||||
else if (sigismember (mask, si.si_signo))
|
||||
masked = true;
|
||||
else if (tls)
|
||||
masked = sigismember (&tls->sigmask, si.si_signo);
|
||||
|
||||
if (masked)
|
||||
if (sigismember (&tls->sigmask, si.si_signo) || ISSTATE (myself, PID_STOPPED))
|
||||
{
|
||||
sigproc_printf ("signal %d blocked", si.si_signo);
|
||||
rc = -1;
|
||||
@ -1240,14 +1203,12 @@ sigpacket::process ()
|
||||
|
||||
if (handler == (void *) SIG_DFL)
|
||||
{
|
||||
if (insigwait_mask)
|
||||
goto thread_specific;
|
||||
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", si.si_signo);
|
||||
if (continue_now)
|
||||
SetEvent (signal_arrived);
|
||||
SetEvent (tls->signal_arrived);
|
||||
goto done;
|
||||
}
|
||||
|
||||
@ -1257,16 +1218,9 @@ sigpacket::process ()
|
||||
goto exit_sig;
|
||||
}
|
||||
|
||||
if (handler == (void *) SIG_IGN)
|
||||
{
|
||||
sigproc_printf ("signal %d ignored", si.si_signo);
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (handler == (void *) SIG_ERR)
|
||||
goto exit_sig;
|
||||
|
||||
use_tls->set_siginfo (this);
|
||||
goto dosig;
|
||||
|
||||
stop:
|
||||
@ -1277,33 +1231,19 @@ stop:
|
||||
thissig = dummy;
|
||||
|
||||
dosig:
|
||||
tls->set_siginfo (this);
|
||||
/* Dispatch to the appropriate function. */
|
||||
sigproc_printf ("signal %d, about to call %p", si.si_signo, handler);
|
||||
rc = setup_handler (si.si_signo, handler, thissig, use_tls);
|
||||
sigproc_printf ("signal %d, signal handler %p", si.si_signo, handler);
|
||||
rc = setup_handler (si.si_signo, handler, thissig, tls);
|
||||
|
||||
done:
|
||||
tls = use_tls;
|
||||
if (continue_now)
|
||||
SetEvent (sigCONT);
|
||||
sigproc_printf ("returning %d", rc);
|
||||
return rc;
|
||||
|
||||
thread_specific:
|
||||
use_tls->sig = si.si_signo;
|
||||
use_tls->set_siginfo (this);
|
||||
use_tls->func = NULL;
|
||||
sigproc_printf ("releasing sigwait for thread");
|
||||
SetEvent (use_tls->event);
|
||||
goto done;
|
||||
|
||||
exit_sig:
|
||||
use_tls->signal_exit (si.si_signo); /* never returns */
|
||||
}
|
||||
|
||||
void
|
||||
events_init ()
|
||||
{
|
||||
mask_sync.init ("mask_sync");
|
||||
tls->signal_exit (si.si_signo); /* never returns */
|
||||
}
|
||||
|
||||
void
|
||||
@ -1321,23 +1261,7 @@ _cygtls::call_signal_handler ()
|
||||
lock ();
|
||||
if (sig)
|
||||
pop ();
|
||||
else if (this != _main_tls)
|
||||
{
|
||||
_main_tls->lock ();
|
||||
if (_main_tls->sig && _main_tls->incyg)
|
||||
{
|
||||
paranoid_printf ("Redirecting to main_tls signal %d", _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)
|
||||
else
|
||||
break;
|
||||
|
||||
debug_only_printf ("dealing with signal %d", sig);
|
||||
@ -1364,7 +1288,7 @@ _cygtls::call_signal_handler ()
|
||||
sigact (thissig, &thissi, NULL);
|
||||
}
|
||||
incyg = true;
|
||||
set_signal_mask (this_oldmask, _my_tls.sigmask);
|
||||
set_signal_mask (_my_tls.sigmask, this_oldmask);
|
||||
if (this_errno >= 0)
|
||||
set_errno (this_errno);
|
||||
}
|
||||
|
Reference in New Issue
Block a user