* child_info.h (cygheap_exec_info::sigmask): Declare new field.
* cygheap.cc (init_cygheap::find_tls): Rename threadlist_ix -> ix. Only take one pass through thread list, looking for eligible threads to signal. Set a new param indicating that function has found a sigwait* mask. * cygheap.h (init_cygheap::find_tls): Reflect new parameter. * dcrt0.cc (parent_sigmask): New variable. (child_info_spawn::handle_spawn): Save parent's signal mask here. (dll_crt0_1): Restore parent's signal mask to tls sigmask as appropriate. Call sig_dispatch_pending to flush signal queue when we can finally do something with signals. * exceptions.cc (sigpacket::process): Avoid attempting to handle signals if we haven't finished initializing. Rely on the fact that find_tls will do mask checking and don't do it again. Delete ill-named 'dummy' variable. * sigproc.cc (cygheap_exec_info::alloc): Save calling thread's signal mask in new sigmask field. (wait_sig): Try to debug when WFSO fails and DEBUGGING is defined. * thread.cc (pthread::set_tls_self_pointer): Make this a true automatic method rather than inexplicably relying on a thread parameter. (pthread::thread_init_wrapper): Accommodate set_tls_self_pointer change to non-static. Initialize sigmask before setting tid or suffer signal races. * ehread.h (pthread::set_tls_self_pointer): Make non-static, delete parameter.
This commit is contained in:
parent
4332090c2d
commit
8f8eeb70ba
|
@ -1,3 +1,31 @@
|
|||
2013-03-31 Christopher Faylor <me.cygwin2013@cgf.cx>
|
||||
|
||||
* child_info.h (cygheap_exec_info::sigmask): Declare new field.
|
||||
* cygheap.cc (init_cygheap::find_tls): Rename threadlist_ix -> ix.
|
||||
Only take one pass through thread list, looking for eligible threads to
|
||||
signal. Set a new param indicating that function has found a sigwait*
|
||||
mask.
|
||||
* cygheap.h (init_cygheap::find_tls): Reflect new parameter.
|
||||
* dcrt0.cc (parent_sigmask): New variable.
|
||||
(child_info_spawn::handle_spawn): Save parent's signal mask here.
|
||||
(dll_crt0_1): Restore parent's signal mask to tls sigmask as
|
||||
appropriate. Call sig_dispatch_pending to flush signal queue when we
|
||||
can finally do something with signals.
|
||||
* exceptions.cc (sigpacket::process): Avoid attempting to handle
|
||||
signals if we haven't finished initializing. Rely on the fact that
|
||||
find_tls will do mask checking and don't do it again. Delete ill-named
|
||||
'dummy' variable.
|
||||
* sigproc.cc (cygheap_exec_info::alloc): Save calling thread's signal
|
||||
mask in new sigmask field.
|
||||
(wait_sig): Try to debug when WFSO fails and DEBUGGING is defined.
|
||||
* thread.cc (pthread::set_tls_self_pointer): Make this a true automatic
|
||||
method rather than inexplicably relying on a thread parameter.
|
||||
(pthread::thread_init_wrapper): Accommodate set_tls_self_pointer change
|
||||
to non-static. Initialize sigmask before setting tid or suffer signal
|
||||
races.
|
||||
* ehread.h (pthread::set_tls_self_pointer): Make non-static, delete
|
||||
parameter.
|
||||
|
||||
2013-03-29 Corinna Vinschen <corinna@vinschen.de>
|
||||
|
||||
* cygthread.cc (cygthread::terminate_thread): Only try to free
|
||||
|
|
|
@ -122,6 +122,7 @@ public:
|
|||
int envc;
|
||||
char **envp;
|
||||
HANDLE myself_pinfo;
|
||||
sigset_t sigmask;
|
||||
int nchildren;
|
||||
cchildren children[0];
|
||||
static cygheap_exec_info *alloc ();
|
||||
|
|
|
@ -611,37 +611,34 @@ init_cygheap::remove_tls (_cygtls *t, DWORD wait)
|
|||
}
|
||||
}
|
||||
|
||||
_cygtls *
|
||||
init_cygheap::find_tls (int sig)
|
||||
_cygtls __reg3 *
|
||||
init_cygheap::find_tls (int sig, bool& issig_wait)
|
||||
{
|
||||
debug_printf ("sig %d\n", sig);
|
||||
tls_sentry here (INFINITE);
|
||||
|
||||
static int NO_COPY threadlist_ix;
|
||||
static int NO_COPY ix;
|
||||
|
||||
_cygtls *t = _main_tls;
|
||||
_cygtls *t = NULL;
|
||||
issig_wait = false;
|
||||
|
||||
myfault efault;
|
||||
if (efault.faulted ())
|
||||
threadlist[threadlist_ix]->remove (INFINITE);
|
||||
threadlist[ix]->remove (INFINITE);
|
||||
else
|
||||
{
|
||||
threadlist_ix = -1;
|
||||
while (++threadlist_ix < (int) nthreads)
|
||||
if (threadlist[threadlist_ix]->tid
|
||||
&& sigismember (&(threadlist[threadlist_ix]->sigwait_mask), sig))
|
||||
ix = -1;
|
||||
while (++ix < (int) nthreads)
|
||||
if (!threadlist[ix]->tid)
|
||||
continue;
|
||||
else if (sigismember (&(threadlist[ix]->sigwait_mask), sig))
|
||||
{
|
||||
t = cygheap->threadlist[threadlist_ix];
|
||||
t = cygheap->threadlist[ix];
|
||||
issig_wait = true;
|
||||
goto out;
|
||||
}
|
||||
threadlist_ix = -1;
|
||||
while (++threadlist_ix < (int) nthreads)
|
||||
if (threadlist[threadlist_ix]->tid
|
||||
&& !sigismember (&(threadlist[threadlist_ix]->sigmask), sig))
|
||||
{
|
||||
t = cygheap->threadlist[threadlist_ix];
|
||||
break;
|
||||
}
|
||||
else if (!t && !sigismember (&(threadlist[ix]->sigmask), sig))
|
||||
t = cygheap->threadlist[ix];
|
||||
}
|
||||
out:
|
||||
return t;
|
||||
|
|
|
@ -398,7 +398,7 @@ struct init_cygheap: public mini_cygheap
|
|||
void __reg1 init_tls_list ();;
|
||||
void __reg2 add_tls (_cygtls *);
|
||||
void __reg3 remove_tls (_cygtls *, DWORD);
|
||||
_cygtls __reg2 *find_tls (int);
|
||||
_cygtls __reg3 *find_tls (int, bool&);
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -397,7 +397,8 @@ check_sanity_and_sync (per_process *p)
|
|||
__cygwin_user_data.cxx_malloc = &default_cygwin_cxx_malloc;
|
||||
}
|
||||
|
||||
child_info NO_COPY *child_proc_info = NULL;
|
||||
child_info NO_COPY *child_proc_info;
|
||||
static NO_COPY sigset_t parent_sigmask;
|
||||
|
||||
#define CYGWIN_GUARD (PAGE_READWRITE | PAGE_GUARD)
|
||||
|
||||
|
@ -654,6 +655,8 @@ child_info_spawn::handle_spawn ()
|
|||
FALSE, DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE))
|
||||
h = NULL;
|
||||
|
||||
parent_sigmask = moreinfo->sigmask;
|
||||
|
||||
/* Setup our write end of the process pipe. Clear the one in the structure.
|
||||
The destructor should never be called for this but, it can't hurt to be
|
||||
safe. */
|
||||
|
@ -821,6 +824,9 @@ dll_crt0_1 (void *)
|
|||
extern void initial_setlocale ();
|
||||
|
||||
_my_tls.incyg++;
|
||||
if (!in_forkee)
|
||||
_my_tls.sigmask = parent_sigmask; /* always zero if started by non-cygwin
|
||||
process */
|
||||
|
||||
if (dynamically_loaded)
|
||||
sigproc_init ();
|
||||
|
@ -1009,6 +1015,7 @@ dll_crt0_1 (void *)
|
|||
while ((*nav++ = *oav++) != NULL)
|
||||
continue;
|
||||
/* Handle any signals which may have arrived */
|
||||
sig_dispatch_pending (false);
|
||||
_my_tls.call_signal_handler ();
|
||||
_my_tls.incyg--; /* Not in Cygwin anymore */
|
||||
cygwin_exit (user_data->main (__argc, newargv, *user_data->envptr));
|
||||
|
|
|
@ -1124,12 +1124,19 @@ signal_exit (int sig, siginfo_t *si)
|
|||
int __stdcall
|
||||
sigpacket::process ()
|
||||
{
|
||||
bool continue_now;
|
||||
struct sigaction dummy = global_sigs[SIGSTOP];
|
||||
int rc = 1;
|
||||
bool issig_wait = false;
|
||||
bool continue_now = false;
|
||||
struct sigaction& thissig = global_sigs[si.si_signo];
|
||||
void *handler = have_execed ? NULL : (void *) thissig.sa_handler;
|
||||
|
||||
if (si.si_signo != SIGCONT)
|
||||
continue_now = false;
|
||||
else
|
||||
if (!cygwin_finished_initializing)
|
||||
{
|
||||
rc = -1;
|
||||
goto really_done;
|
||||
}
|
||||
|
||||
if (si.si_signo == SIGCONT)
|
||||
{
|
||||
continue_now = ISSTATE (myself, PID_STOPPED);
|
||||
myself->stopsig = 0;
|
||||
|
@ -1141,30 +1148,43 @@ sigpacket::process ()
|
|||
sig_clear (SIGTTOU);
|
||||
}
|
||||
|
||||
int rc = 1;
|
||||
|
||||
sigproc_printf ("signal %d processing", si.si_signo);
|
||||
struct sigaction& thissig = global_sigs[si.si_signo];
|
||||
|
||||
myself->rusage_self.ru_nsignals++;
|
||||
|
||||
_cygtls *tls;
|
||||
if (sigtls)
|
||||
if (!sigtls)
|
||||
{
|
||||
tls = sigtls;
|
||||
sigproc_printf ("using sigtls %p", sigtls);
|
||||
tls = cygheap->find_tls (si.si_signo, issig_wait);
|
||||
sigproc_printf ("using tls %p", tls);
|
||||
}
|
||||
else
|
||||
{
|
||||
tls = cygheap->find_tls (si.si_signo);
|
||||
sigproc_printf ("using tls %p", tls);
|
||||
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;
|
||||
}
|
||||
|
||||
if (!tls || ISSTATE (myself, PID_STOPPED))
|
||||
{
|
||||
sigproc_printf ("signal %d blocked", si.si_signo);
|
||||
rc = -1;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* Do stuff for gdb */
|
||||
if ((HANDLE) *tls)
|
||||
tls->signal_debugger (si);
|
||||
|
||||
void *handler = have_execed ? NULL : (void *) thissig.sa_handler;
|
||||
if (issig_wait)
|
||||
{
|
||||
tls->sigwait_mask = 0;
|
||||
goto dosig;
|
||||
}
|
||||
|
||||
if (handler == SIG_IGN)
|
||||
{
|
||||
|
@ -1180,18 +1200,6 @@ sigpacket::process ()
|
|||
goto stop;
|
||||
}
|
||||
|
||||
if (sigismember (&tls->sigwait_mask, si.si_signo))
|
||||
{
|
||||
tls->sigwait_mask = 0;
|
||||
goto dosig;
|
||||
}
|
||||
if (sigismember (&tls->sigmask, si.si_signo) || ISSTATE (myself, PID_STOPPED))
|
||||
{
|
||||
sigproc_printf ("signal %d blocked", si.si_signo);
|
||||
rc = -1;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* Clear pending SIGCONT on stop signals */
|
||||
if (si.si_signo == SIGTSTP || si.si_signo == SIGTTIN || si.si_signo == SIGTTOU)
|
||||
sig_clear (SIGCONT);
|
||||
|
@ -1218,7 +1226,7 @@ sigpacket::process ()
|
|||
|
||||
stop:
|
||||
handler = (void *) sig_handle_tty_stop;
|
||||
thissig = dummy;
|
||||
thissig = global_sigs[SIGSTOP];
|
||||
goto dosig;
|
||||
|
||||
exit_sig:
|
||||
|
@ -1248,9 +1256,10 @@ dispatch_sig:
|
|||
done:
|
||||
if (continue_now)
|
||||
{
|
||||
tls->sig = SIGCONT;
|
||||
(tls ?: _main_tls)->sig = SIGCONT;
|
||||
SetEvent (tls->signal_arrived);
|
||||
}
|
||||
really_done:
|
||||
sigproc_printf ("returning %d", rc);
|
||||
return rc;
|
||||
|
||||
|
|
|
@ -835,9 +835,12 @@ child_info_spawn::child_info_spawn (child_info_types chtype, bool need_subproc_r
|
|||
cygheap_exec_info *
|
||||
cygheap_exec_info::alloc ()
|
||||
{
|
||||
return (cygheap_exec_info *) ccalloc_abort (HEAP_1_EXEC, 1,
|
||||
sizeof (cygheap_exec_info)
|
||||
+ (nprocs * sizeof (children[0])));
|
||||
cygheap_exec_info *res =
|
||||
(cygheap_exec_info *) ccalloc_abort (HEAP_1_EXEC, 1,
|
||||
sizeof (cygheap_exec_info)
|
||||
+ (nprocs * sizeof (children[0])));
|
||||
res->sigmask = _my_tls.sigmask;
|
||||
return res;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -1237,7 +1240,6 @@ pending_signals::add (sigpacket& pack)
|
|||
if (se->si.si_signo)
|
||||
return;
|
||||
*se = pack;
|
||||
se->mask = &pack.sigtls->sigmask;
|
||||
se->next = NULL;
|
||||
if (end)
|
||||
end->next = se;
|
||||
|
@ -1365,7 +1367,12 @@ wait_sig (VOID *)
|
|||
lock_process::force_release (pack.sigtls);
|
||||
ForceCloseHandle1 (h, exit_thread);
|
||||
if (res != WAIT_OBJECT_0)
|
||||
system_printf ("WaitForSingleObject(%p) for thread exit returned %u", h, res);
|
||||
{
|
||||
#ifdef DEBUGGING
|
||||
try_to_debug();
|
||||
#endif
|
||||
system_printf ("WaitForSingleObject(%p) for thread exit returned %u", h, res);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/* spawn.cc
|
||||
|
||||
Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
|
||||
2007, 2008, 2009, 2010, 2011, 2012 Red Hat, Inc.
|
||||
2007, 2008, 2009, 2010, 2011, 2012, 2013 Red Hat, Inc.
|
||||
|
||||
This file is part of Cygwin.
|
||||
|
||||
|
|
|
@ -338,7 +338,7 @@ pthread::init_mainthread ()
|
|||
api_fatal ("failed to create mainthread object");
|
||||
}
|
||||
|
||||
set_tls_self_pointer (thread);
|
||||
thread->set_tls_self_pointer ();
|
||||
thread->thread_id = GetCurrentThreadId ();
|
||||
if (!DuplicateHandle (GetCurrentProcess (), GetCurrentThread (),
|
||||
GetCurrentProcess (), &thread->win32_obj_id,
|
||||
|
@ -357,16 +357,16 @@ pthread::self ()
|
|||
if (!thread)
|
||||
{
|
||||
thread = pthread_null::get_null_pthread ();
|
||||
set_tls_self_pointer (thread);
|
||||
thread->set_tls_self_pointer ();
|
||||
}
|
||||
return thread;
|
||||
}
|
||||
|
||||
void
|
||||
pthread::set_tls_self_pointer (pthread *thread)
|
||||
pthread::set_tls_self_pointer ()
|
||||
{
|
||||
thread->cygtls = &_my_tls;
|
||||
_my_tls.tid = thread;
|
||||
cygtls = &_my_tls;
|
||||
_my_tls.tid = this;
|
||||
}
|
||||
|
||||
List<pthread> pthread::threads;
|
||||
|
@ -1912,14 +1912,14 @@ DWORD WINAPI
|
|||
pthread::thread_init_wrapper (void *arg)
|
||||
{
|
||||
pthread *thread = (pthread *) arg;
|
||||
set_tls_self_pointer (thread);
|
||||
_my_tls.sigmask = thread->parent_sigmask;
|
||||
thread->set_tls_self_pointer ();
|
||||
|
||||
thread->mutex.lock ();
|
||||
|
||||
// if thread is detached force cleanup on exit
|
||||
if (thread->attr.joinable == PTHREAD_CREATE_DETACHED && thread->joiner == NULL)
|
||||
thread->joiner = thread;
|
||||
_my_tls.sigmask = thread->parent_sigmask;
|
||||
thread->mutex.unlock ();
|
||||
|
||||
debug_printf ("tid %p", &_my_tls);
|
||||
|
|
|
@ -443,7 +443,7 @@ private:
|
|||
void precreate (pthread_attr *);
|
||||
void postcreate ();
|
||||
bool create_cancel_event ();
|
||||
static void set_tls_self_pointer (pthread *);
|
||||
void set_tls_self_pointer ();
|
||||
void cancel_self () __attribute__ ((noreturn));
|
||||
DWORD get_thread_id ();
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue