* 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>
|
2013-03-29 Corinna Vinschen <corinna@vinschen.de>
|
||||||
|
|
||||||
* cygthread.cc (cygthread::terminate_thread): Only try to free
|
* cygthread.cc (cygthread::terminate_thread): Only try to free
|
||||||
|
|
|
@ -122,6 +122,7 @@ public:
|
||||||
int envc;
|
int envc;
|
||||||
char **envp;
|
char **envp;
|
||||||
HANDLE myself_pinfo;
|
HANDLE myself_pinfo;
|
||||||
|
sigset_t sigmask;
|
||||||
int nchildren;
|
int nchildren;
|
||||||
cchildren children[0];
|
cchildren children[0];
|
||||||
static cygheap_exec_info *alloc ();
|
static cygheap_exec_info *alloc ();
|
||||||
|
|
|
@ -611,37 +611,34 @@ init_cygheap::remove_tls (_cygtls *t, DWORD wait)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_cygtls *
|
_cygtls __reg3 *
|
||||||
init_cygheap::find_tls (int sig)
|
init_cygheap::find_tls (int sig, bool& issig_wait)
|
||||||
{
|
{
|
||||||
debug_printf ("sig %d\n", sig);
|
debug_printf ("sig %d\n", sig);
|
||||||
tls_sentry here (INFINITE);
|
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;
|
myfault efault;
|
||||||
if (efault.faulted ())
|
if (efault.faulted ())
|
||||||
threadlist[threadlist_ix]->remove (INFINITE);
|
threadlist[ix]->remove (INFINITE);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
threadlist_ix = -1;
|
ix = -1;
|
||||||
while (++threadlist_ix < (int) nthreads)
|
while (++ix < (int) nthreads)
|
||||||
if (threadlist[threadlist_ix]->tid
|
if (!threadlist[ix]->tid)
|
||||||
&& sigismember (&(threadlist[threadlist_ix]->sigwait_mask), sig))
|
continue;
|
||||||
|
else if (sigismember (&(threadlist[ix]->sigwait_mask), sig))
|
||||||
{
|
{
|
||||||
t = cygheap->threadlist[threadlist_ix];
|
t = cygheap->threadlist[ix];
|
||||||
|
issig_wait = true;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
threadlist_ix = -1;
|
else if (!t && !sigismember (&(threadlist[ix]->sigmask), sig))
|
||||||
while (++threadlist_ix < (int) nthreads)
|
t = cygheap->threadlist[ix];
|
||||||
if (threadlist[threadlist_ix]->tid
|
|
||||||
&& !sigismember (&(threadlist[threadlist_ix]->sigmask), sig))
|
|
||||||
{
|
|
||||||
t = cygheap->threadlist[threadlist_ix];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
out:
|
out:
|
||||||
return t;
|
return t;
|
||||||
|
|
|
@ -398,7 +398,7 @@ struct init_cygheap: public mini_cygheap
|
||||||
void __reg1 init_tls_list ();;
|
void __reg1 init_tls_list ();;
|
||||||
void __reg2 add_tls (_cygtls *);
|
void __reg2 add_tls (_cygtls *);
|
||||||
void __reg3 remove_tls (_cygtls *, DWORD);
|
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;
|
__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)
|
#define CYGWIN_GUARD (PAGE_READWRITE | PAGE_GUARD)
|
||||||
|
|
||||||
|
@ -654,6 +655,8 @@ child_info_spawn::handle_spawn ()
|
||||||
FALSE, DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE))
|
FALSE, DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE))
|
||||||
h = NULL;
|
h = NULL;
|
||||||
|
|
||||||
|
parent_sigmask = moreinfo->sigmask;
|
||||||
|
|
||||||
/* Setup our write end of the process pipe. Clear the one in the structure.
|
/* 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
|
The destructor should never be called for this but, it can't hurt to be
|
||||||
safe. */
|
safe. */
|
||||||
|
@ -821,6 +824,9 @@ dll_crt0_1 (void *)
|
||||||
extern void initial_setlocale ();
|
extern void initial_setlocale ();
|
||||||
|
|
||||||
_my_tls.incyg++;
|
_my_tls.incyg++;
|
||||||
|
if (!in_forkee)
|
||||||
|
_my_tls.sigmask = parent_sigmask; /* always zero if started by non-cygwin
|
||||||
|
process */
|
||||||
|
|
||||||
if (dynamically_loaded)
|
if (dynamically_loaded)
|
||||||
sigproc_init ();
|
sigproc_init ();
|
||||||
|
@ -1009,6 +1015,7 @@ dll_crt0_1 (void *)
|
||||||
while ((*nav++ = *oav++) != NULL)
|
while ((*nav++ = *oav++) != NULL)
|
||||||
continue;
|
continue;
|
||||||
/* Handle any signals which may have arrived */
|
/* Handle any signals which may have arrived */
|
||||||
|
sig_dispatch_pending (false);
|
||||||
_my_tls.call_signal_handler ();
|
_my_tls.call_signal_handler ();
|
||||||
_my_tls.incyg--; /* Not in Cygwin anymore */
|
_my_tls.incyg--; /* Not in Cygwin anymore */
|
||||||
cygwin_exit (user_data->main (__argc, newargv, *user_data->envptr));
|
cygwin_exit (user_data->main (__argc, newargv, *user_data->envptr));
|
||||||
|
|
|
@ -1124,12 +1124,19 @@ signal_exit (int sig, siginfo_t *si)
|
||||||
int __stdcall
|
int __stdcall
|
||||||
sigpacket::process ()
|
sigpacket::process ()
|
||||||
{
|
{
|
||||||
bool continue_now;
|
int rc = 1;
|
||||||
struct sigaction dummy = global_sigs[SIGSTOP];
|
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)
|
if (!cygwin_finished_initializing)
|
||||||
continue_now = false;
|
{
|
||||||
else
|
rc = -1;
|
||||||
|
goto really_done;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (si.si_signo == SIGCONT)
|
||||||
{
|
{
|
||||||
continue_now = ISSTATE (myself, PID_STOPPED);
|
continue_now = ISSTATE (myself, PID_STOPPED);
|
||||||
myself->stopsig = 0;
|
myself->stopsig = 0;
|
||||||
|
@ -1141,30 +1148,43 @@ sigpacket::process ()
|
||||||
sig_clear (SIGTTOU);
|
sig_clear (SIGTTOU);
|
||||||
}
|
}
|
||||||
|
|
||||||
int rc = 1;
|
|
||||||
|
|
||||||
sigproc_printf ("signal %d processing", si.si_signo);
|
sigproc_printf ("signal %d processing", si.si_signo);
|
||||||
struct sigaction& thissig = global_sigs[si.si_signo];
|
|
||||||
|
|
||||||
myself->rusage_self.ru_nsignals++;
|
myself->rusage_self.ru_nsignals++;
|
||||||
|
|
||||||
_cygtls *tls;
|
_cygtls *tls;
|
||||||
if (sigtls)
|
if (!sigtls)
|
||||||
{
|
{
|
||||||
tls = sigtls;
|
tls = cygheap->find_tls (si.si_signo, issig_wait);
|
||||||
sigproc_printf ("using sigtls %p", sigtls);
|
sigproc_printf ("using tls %p", tls);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
tls = cygheap->find_tls (si.si_signo);
|
tls = sigtls;
|
||||||
sigproc_printf ("using tls %p", tls);
|
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 */
|
/* Do stuff for gdb */
|
||||||
if ((HANDLE) *tls)
|
if ((HANDLE) *tls)
|
||||||
tls->signal_debugger (si);
|
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)
|
if (handler == SIG_IGN)
|
||||||
{
|
{
|
||||||
|
@ -1180,18 +1200,6 @@ sigpacket::process ()
|
||||||
goto stop;
|
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 */
|
/* 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);
|
sig_clear (SIGCONT);
|
||||||
|
@ -1218,7 +1226,7 @@ sigpacket::process ()
|
||||||
|
|
||||||
stop:
|
stop:
|
||||||
handler = (void *) sig_handle_tty_stop;
|
handler = (void *) sig_handle_tty_stop;
|
||||||
thissig = dummy;
|
thissig = global_sigs[SIGSTOP];
|
||||||
goto dosig;
|
goto dosig;
|
||||||
|
|
||||||
exit_sig:
|
exit_sig:
|
||||||
|
@ -1248,9 +1256,10 @@ dispatch_sig:
|
||||||
done:
|
done:
|
||||||
if (continue_now)
|
if (continue_now)
|
||||||
{
|
{
|
||||||
tls->sig = SIGCONT;
|
(tls ?: _main_tls)->sig = SIGCONT;
|
||||||
SetEvent (tls->signal_arrived);
|
SetEvent (tls->signal_arrived);
|
||||||
}
|
}
|
||||||
|
really_done:
|
||||||
sigproc_printf ("returning %d", rc);
|
sigproc_printf ("returning %d", rc);
|
||||||
return 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 *
|
||||||
cygheap_exec_info::alloc ()
|
cygheap_exec_info::alloc ()
|
||||||
{
|
{
|
||||||
return (cygheap_exec_info *) ccalloc_abort (HEAP_1_EXEC, 1,
|
cygheap_exec_info *res =
|
||||||
sizeof (cygheap_exec_info)
|
(cygheap_exec_info *) ccalloc_abort (HEAP_1_EXEC, 1,
|
||||||
+ (nprocs * sizeof (children[0])));
|
sizeof (cygheap_exec_info)
|
||||||
|
+ (nprocs * sizeof (children[0])));
|
||||||
|
res->sigmask = _my_tls.sigmask;
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -1237,7 +1240,6 @@ pending_signals::add (sigpacket& pack)
|
||||||
if (se->si.si_signo)
|
if (se->si.si_signo)
|
||||||
return;
|
return;
|
||||||
*se = pack;
|
*se = pack;
|
||||||
se->mask = &pack.sigtls->sigmask;
|
|
||||||
se->next = NULL;
|
se->next = NULL;
|
||||||
if (end)
|
if (end)
|
||||||
end->next = se;
|
end->next = se;
|
||||||
|
@ -1365,7 +1367,12 @@ wait_sig (VOID *)
|
||||||
lock_process::force_release (pack.sigtls);
|
lock_process::force_release (pack.sigtls);
|
||||||
ForceCloseHandle1 (h, exit_thread);
|
ForceCloseHandle1 (h, exit_thread);
|
||||||
if (res != WAIT_OBJECT_0)
|
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;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/* spawn.cc
|
/* spawn.cc
|
||||||
|
|
||||||
Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
|
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.
|
This file is part of Cygwin.
|
||||||
|
|
||||||
|
|
|
@ -338,7 +338,7 @@ pthread::init_mainthread ()
|
||||||
api_fatal ("failed to create mainthread object");
|
api_fatal ("failed to create mainthread object");
|
||||||
}
|
}
|
||||||
|
|
||||||
set_tls_self_pointer (thread);
|
thread->set_tls_self_pointer ();
|
||||||
thread->thread_id = GetCurrentThreadId ();
|
thread->thread_id = GetCurrentThreadId ();
|
||||||
if (!DuplicateHandle (GetCurrentProcess (), GetCurrentThread (),
|
if (!DuplicateHandle (GetCurrentProcess (), GetCurrentThread (),
|
||||||
GetCurrentProcess (), &thread->win32_obj_id,
|
GetCurrentProcess (), &thread->win32_obj_id,
|
||||||
|
@ -357,16 +357,16 @@ pthread::self ()
|
||||||
if (!thread)
|
if (!thread)
|
||||||
{
|
{
|
||||||
thread = pthread_null::get_null_pthread ();
|
thread = pthread_null::get_null_pthread ();
|
||||||
set_tls_self_pointer (thread);
|
thread->set_tls_self_pointer ();
|
||||||
}
|
}
|
||||||
return thread;
|
return thread;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
pthread::set_tls_self_pointer (pthread *thread)
|
pthread::set_tls_self_pointer ()
|
||||||
{
|
{
|
||||||
thread->cygtls = &_my_tls;
|
cygtls = &_my_tls;
|
||||||
_my_tls.tid = thread;
|
_my_tls.tid = this;
|
||||||
}
|
}
|
||||||
|
|
||||||
List<pthread> pthread::threads;
|
List<pthread> pthread::threads;
|
||||||
|
@ -1912,14 +1912,14 @@ DWORD WINAPI
|
||||||
pthread::thread_init_wrapper (void *arg)
|
pthread::thread_init_wrapper (void *arg)
|
||||||
{
|
{
|
||||||
pthread *thread = (pthread *) arg;
|
pthread *thread = (pthread *) arg;
|
||||||
set_tls_self_pointer (thread);
|
_my_tls.sigmask = thread->parent_sigmask;
|
||||||
|
thread->set_tls_self_pointer ();
|
||||||
|
|
||||||
thread->mutex.lock ();
|
thread->mutex.lock ();
|
||||||
|
|
||||||
// if thread is detached force cleanup on exit
|
// if thread is detached force cleanup on exit
|
||||||
if (thread->attr.joinable == PTHREAD_CREATE_DETACHED && thread->joiner == NULL)
|
if (thread->attr.joinable == PTHREAD_CREATE_DETACHED && thread->joiner == NULL)
|
||||||
thread->joiner = thread;
|
thread->joiner = thread;
|
||||||
_my_tls.sigmask = thread->parent_sigmask;
|
|
||||||
thread->mutex.unlock ();
|
thread->mutex.unlock ();
|
||||||
|
|
||||||
debug_printf ("tid %p", &_my_tls);
|
debug_printf ("tid %p", &_my_tls);
|
||||||
|
|
|
@ -443,7 +443,7 @@ private:
|
||||||
void precreate (pthread_attr *);
|
void precreate (pthread_attr *);
|
||||||
void postcreate ();
|
void postcreate ();
|
||||||
bool create_cancel_event ();
|
bool create_cancel_event ();
|
||||||
static void set_tls_self_pointer (pthread *);
|
void set_tls_self_pointer ();
|
||||||
void cancel_self () __attribute__ ((noreturn));
|
void cancel_self () __attribute__ ((noreturn));
|
||||||
DWORD get_thread_id ();
|
DWORD get_thread_id ();
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue