Welcome to mirror list, hosted at ThFree Co, Russian Federation.

cygwin.com/git/newlib-cygwin.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristopher Faylor <me@cgf.cx>2013-03-31 16:35:44 +0400
committerChristopher Faylor <me@cgf.cx>2013-03-31 16:35:44 +0400
commit8f8eeb70ba7354749c78bc5013eeb12f4c18fba0 (patch)
tree5a33777acf2ae03b9f4ef75de12bdccecd1df068
parent4332090c2d497c08dd1c98df7702f861905b2508 (diff)
* 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.
-rw-r--r--winsup/cygwin/ChangeLog28
-rw-r--r--winsup/cygwin/child_info.h1
-rw-r--r--winsup/cygwin/cygheap.cc33
-rw-r--r--winsup/cygwin/cygheap.h2
-rw-r--r--winsup/cygwin/dcrt0.cc9
-rw-r--r--winsup/cygwin/exceptions.cc65
-rw-r--r--winsup/cygwin/sigproc.cc17
-rw-r--r--winsup/cygwin/spawn.cc2
-rw-r--r--winsup/cygwin/thread.cc14
-rw-r--r--winsup/cygwin/thread.h2
10 files changed, 111 insertions, 62 deletions
diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog
index 7b19686ae..4b04b3334 100644
--- a/winsup/cygwin/ChangeLog
+++ b/winsup/cygwin/ChangeLog
@@ -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
diff --git a/winsup/cygwin/child_info.h b/winsup/cygwin/child_info.h
index 66d6b95aa..17da88ec6 100644
--- a/winsup/cygwin/child_info.h
+++ b/winsup/cygwin/child_info.h
@@ -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 ();
diff --git a/winsup/cygwin/cygheap.cc b/winsup/cygwin/cygheap.cc
index f0a4e3e96..7ac30122b 100644
--- a/winsup/cygwin/cygheap.cc
+++ b/winsup/cygwin/cygheap.cc
@@ -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;
diff --git a/winsup/cygwin/cygheap.h b/winsup/cygwin/cygheap.h
index 4cade6a2b..b51076472 100644
--- a/winsup/cygwin/cygheap.h
+++ b/winsup/cygwin/cygheap.h
@@ -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&);
};
diff --git a/winsup/cygwin/dcrt0.cc b/winsup/cygwin/dcrt0.cc
index 094c0a09a..f7f7756a2 100644
--- a/winsup/cygwin/dcrt0.cc
+++ b/winsup/cygwin/dcrt0.cc
@@ -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));
diff --git a/winsup/cygwin/exceptions.cc b/winsup/cygwin/exceptions.cc
index e41922900..9815be280 100644
--- a/winsup/cygwin/exceptions.cc
+++ b/winsup/cygwin/exceptions.cc
@@ -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;
diff --git a/winsup/cygwin/sigproc.cc b/winsup/cygwin/sigproc.cc
index 015cbaf2b..4bf6f5630 100644
--- a/winsup/cygwin/sigproc.cc
+++ b/winsup/cygwin/sigproc.cc
@@ -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;
}
diff --git a/winsup/cygwin/spawn.cc b/winsup/cygwin/spawn.cc
index 5d2942bef..4ed3221dd 100644
--- a/winsup/cygwin/spawn.cc
+++ b/winsup/cygwin/spawn.cc
@@ -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.
diff --git a/winsup/cygwin/thread.cc b/winsup/cygwin/thread.cc
index 38d718fb3..699b34479 100644
--- a/winsup/cygwin/thread.cc
+++ b/winsup/cygwin/thread.cc
@@ -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);
diff --git a/winsup/cygwin/thread.h b/winsup/cygwin/thread.h
index 218e70f6a..71f301258 100644
--- a/winsup/cygwin/thread.h
+++ b/winsup/cygwin/thread.h
@@ -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 ();
};