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:
-rw-r--r--winsup/cygwin/ChangeLog57
-rw-r--r--winsup/cygwin/cygheap.h2
-rw-r--r--winsup/cygwin/cygtls.cc48
-rw-r--r--winsup/cygwin/cygtls.h17
-rw-r--r--winsup/cygwin/dcrt0.cc23
-rw-r--r--winsup/cygwin/dll_init.cc4
-rw-r--r--winsup/cygwin/exceptions.cc106
-rw-r--r--winsup/cygwin/fork.cc50
-rwxr-xr-xwinsup/cygwin/gendef131
-rw-r--r--winsup/cygwin/init.cc2
-rw-r--r--winsup/cygwin/miscfuncs.cc2
-rw-r--r--winsup/cygwin/perthread.h2
-rw-r--r--winsup/cygwin/pinfo.cc13
-rw-r--r--winsup/cygwin/pinfo.h2
-rw-r--r--winsup/cygwin/signal.cc6
-rw-r--r--winsup/cygwin/sigproc.cc6
-rw-r--r--winsup/cygwin/sigproc.h5
-rw-r--r--winsup/cygwin/sync.cc4
-rw-r--r--winsup/cygwin/syscalls.cc2
-rw-r--r--winsup/cygwin/termios.cc3
-rw-r--r--winsup/cygwin/thread.h4
-rw-r--r--winsup/cygwin/wait.cc5
-rw-r--r--winsup/cygwin/winsup.h2
23 files changed, 287 insertions, 209 deletions
diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog
index 852c1839f..2cc0cb88b 100644
--- a/winsup/cygwin/ChangeLog
+++ b/winsup/cygwin/ChangeLog
@@ -1,3 +1,60 @@
+2004-02-11 Christopher Faylor <cgf@redhat.com>
+
+ Rename _threadinfo to _cygtls, throughout.
+ * cygtls.h (_cygtls::call_signal_handler): Rename from
+ call_signal_handler_now.
+ (_cygtls::push): Make second argument mandatory.
+ (_cygtls::fixup_after_fork): Declare new function.
+ (_cygtls::lock): Ditto.
+ * cygtls.cc (_cygtls::fixup_after_fork): Define new function.
+ * dcrt0.cc (cygwin_finished_initializing): Define as bool.
+ (alloc_stack): Use _tlstop rather than arbitrary variable in probably
+ vain attempt to avoid strange fork problem on CTRL-C.
+ (dll_crt0_0): Remove obsolete winpids::init call.
+ * dll_init.cc (dll_dllcrt0): Detect forkee condition as equivalent to
+ initializing.
+ * winsup.h (cygwin_finished_initializing): Declare as bool.
+ * exceptions.cc (handle_exceptions): Rely on
+ cygwin_finished_initializing to determine how to handle exception
+ during process startup.
+ (_cygtls::call_signal_handler): Rename from call_signal_handler_now.
+ (_cygtls::interrupt_now): Fill in second argument to push.
+ (signal_fixup_after_fork): Eliminate.
+ (setup_handler): Initialize locked to avoid potential inappropriate
+ unlock. Resume thread if it has acquired the stack lock.
+ (ctrl_c_handler): Just exit if ctrl-c is hit before cygiwn has finished
+ initializing.
+ * fork.cc (sync_with_child): Don't call abort since it can cause exit
+ deadlocks.
+ (sync_with_child): Change debugging output slightly.
+ (fork_child): Set cygwin_finished_initializing here. Call _cygtls fork
+ fixup and explicitly call sigproc_init.
+ (fork_parent): Release malloc lock on fork failure.
+ (vfork): Call signal handler via _my_tls.
+ * sigproc.cc (sig_send): Ditto.
+ * syscalls.cc (readv): Ditto.
+ * termios.cc (tcsetattr): Ditto.
+ * wait.cc (wait4): Ditto.
+ * signal.cc (nanosleep): Ditto.
+ (abort): Ditto.
+ (kill_pgrp): Avoid killing self if exiting.
+ * sync.cc (muto::acquire): Remove (temporarily?) ill-advised
+ exiting_thread check.
+ * gendef (_sigfe): Be more agressive in protecting stack pointer from
+ other access by signal thread.
+ (_cygtls::locked): Define new function.
+ (_sigbe): Ditto.
+ (_cygtls::pop): Protect edx.
+ (_cygtls::lock): Use guaranteed method to set eax to 1.
+ (longjmp): Aggressively protect signal stack.
+ * miscfuncs.cc (low_priority_sleep): Reduce "sleep time" for secs == 0.
+ * pinfo.cc (winpids::set): Counterintuitively use malloc's lock to
+ protect simultaneous access to the pids list since there are
+ pathological conditions which can cause malloc to call winpid.
+ (winpids::init): Eliminate.
+ * pinfo.h (winpids::cs): Eliminate declaration.
+ * pinfo.h (winpids::init): Eliminate definition.
+
2004-02-11 Corinna Vinschen <corinna@vinschen.de>
* security.cc (get_nt_object_attribute): Fix error handling.
diff --git a/winsup/cygwin/cygheap.h b/winsup/cygwin/cygheap.h
index a5134cfde..518e9dce6 100644
--- a/winsup/cygwin/cygheap.h
+++ b/winsup/cygwin/cygheap.h
@@ -266,7 +266,7 @@ struct init_cygheap
#ifdef NEWVFORK
fhandler_tty_slave *ctty_on_hold;
#endif
- struct _threadinfo **threadlist;
+ struct _cygtls **threadlist;
size_t sthreads;
int open_fhs;
void close_ctty ();
diff --git a/winsup/cygwin/cygtls.cc b/winsup/cygwin/cygtls.cc
index d3ed824c8..89e21d473 100644
--- a/winsup/cygwin/cygtls.cc
+++ b/winsup/cygwin/cygtls.cc
@@ -20,6 +20,7 @@ details. */
#include "dtable.h"
#include "cygheap.h"
#include "cygthread.h"
+#include "pinfo.h"
#include "sigproc.h"
class sentry
@@ -32,7 +33,7 @@ public:
sentry () {destroy = 0;}
sentry (DWORD wait) {destroy = lock->acquire (wait);}
~sentry () {if (destroy) lock->release ();}
- friend void _threadinfo::init ();
+ friend void _cygtls::init ();
};
muto NO_COPY *sentry::lock;
@@ -42,27 +43,27 @@ static size_t NO_COPY nthreads;
#define THREADLIST_CHUNK 256
void
-_threadinfo::init ()
+_cygtls::init ()
{
if (cygheap->threadlist)
memset (cygheap->threadlist, 0, cygheap->sthreads * sizeof (cygheap->threadlist[0]));
else
{
cygheap->sthreads = THREADLIST_CHUNK;
- cygheap->threadlist = (_threadinfo **) ccalloc (HEAP_TLS, cygheap->sthreads,
+ cygheap->threadlist = (_cygtls **) ccalloc (HEAP_TLS, cygheap->sthreads,
sizeof (cygheap->threadlist[0]));
}
new_muto1 (sentry::lock, sentry_lock);
}
void
-_threadinfo::set_state (bool is_exception)
+_cygtls::set_state (bool is_exception)
{
initialized = CYGTLS_INITIALIZED + is_exception;
}
void
-_threadinfo::reset_exception ()
+_cygtls::reset_exception ()
{
if (initialized == CYGTLS_EXCEPTION)
{
@@ -75,14 +76,14 @@ _threadinfo::reset_exception ()
/* Two calls to get the stack right... */
void
-_threadinfo::call (DWORD (*func) (void *, void *), void *arg)
+_cygtls::call (DWORD (*func) (void *, void *), void *arg)
{
char buf[CYGTLS_PADSIZE];
call2 (func, arg, buf);
}
void
-_threadinfo::call2 (DWORD (*func) (void *, void *), void *arg, void *buf)
+_cygtls::call2 (DWORD (*func) (void *, void *), void *arg, void *buf)
{
exception_list except_entry;
/* Initialize this thread's ability to respond to things like
@@ -95,7 +96,7 @@ _threadinfo::call2 (DWORD (*func) (void *, void *), void *arg, void *buf)
}
void
-_threadinfo::init_thread (void *x, DWORD (*func) (void *, void *))
+_cygtls::init_thread (void *x, DWORD (*func) (void *, void *))
{
if (x)
{
@@ -125,7 +126,7 @@ _threadinfo::init_thread (void *x, DWORD (*func) (void *, void *))
sentry here (INFINITE);
if (nthreads >= cygheap->sthreads)
{
- cygheap->threadlist = (_threadinfo **)
+ cygheap->threadlist = (_cygtls **)
crealloc (cygheap->threadlist, (cygheap->sthreads += THREADLIST_CHUNK)
* sizeof (cygheap->threadlist[0]));
memset (cygheap->threadlist + nthreads, 0, THREADLIST_CHUNK * sizeof (cygheap->threadlist[0]));
@@ -135,7 +136,22 @@ _threadinfo::init_thread (void *x, DWORD (*func) (void *, void *))
}
void
-_threadinfo::remove (DWORD wait)
+_cygtls::fixup_after_fork ()
+{
+ if (sig)
+ {
+ set_signal_mask (oldmask);
+ sig = 0;
+ }
+ stacklock = 0;
+ stackptr = stack + 1; // FIXME?
+#ifdef DEBUGGING
+ memset (stackptr, 0, sizeof (stack) - sizeof (stack[0]));
+#endif
+}
+
+void
+_cygtls::remove (DWORD wait)
{
debug_printf ("wait %p\n", wait);
sentry here (wait);
@@ -153,7 +169,7 @@ _threadinfo::remove (DWORD wait)
}
void
-_threadinfo::push (__stack_t addr, bool exception)
+_cygtls::push (__stack_t addr, bool exception)
{
if (exception)
lock ();
@@ -166,13 +182,13 @@ _threadinfo::push (__stack_t addr, bool exception)
#define BAD_IX ((size_t) -1)
static size_t NO_COPY threadlist_ix = BAD_IX;
-_threadinfo *
-_threadinfo::find_tls (int sig)
+_cygtls *
+_cygtls::find_tls (int sig)
{
debug_printf ("sig %d\n", sig);
sentry here (INFINITE);
__asm__ volatile (".equ _threadlist_exception_return,.");
- _threadinfo *res = NULL;
+ _cygtls *res = NULL;
for (threadlist_ix = 0; threadlist_ix < nthreads; threadlist_ix++)
if (sigismember (&(cygheap->threadlist[threadlist_ix]->sigwait_mask), sig))
{
@@ -184,7 +200,7 @@ _threadinfo::find_tls (int sig)
}
void
-_threadinfo::set_siginfo (sigpacket *pack)
+_cygtls::set_siginfo (sigpacket *pack)
{
infodata = pack->si;
}
@@ -222,7 +238,7 @@ handle_threadlist_exception (EXCEPTION_RECORD *e, void *frame, CONTEXT *, void *
}
void
-_threadinfo::init_threadlist_exceptions (exception_list *el)
+_cygtls::init_threadlist_exceptions (exception_list *el)
{
extern void init_exception_handler (exception_list *, exception_handler *);
init_exception_handler (el, handle_threadlist_exception);
diff --git a/winsup/cygwin/cygtls.h b/winsup/cygwin/cygtls.h
index 43802dd81..78f61242b 100644
--- a/winsup/cygwin/cygtls.h
+++ b/winsup/cygwin/cygtls.h
@@ -90,7 +90,7 @@ struct _local_storage
'gentls_offsets' (<<-- start parsing here). */
typedef __uint32_t __stack_t;
-struct _threadinfo
+struct _cygtls
{
void (*func) /*gentls_offsets*/(int)/*gentls_offsets*/;
int saved_errno;
@@ -108,7 +108,7 @@ struct _threadinfo
struct pthread *tid;
struct _reent local_clib;
struct _local_storage locals;
- struct _threadinfo *prev, *next;
+ struct _cygtls *prev, *next;
__stack_t *stackptr;
int sig;
unsigned stacklock;
@@ -121,9 +121,9 @@ struct _threadinfo
void init_thread (void *, DWORD (*) (void *, void *));
static void call (DWORD (*) (void *, void *), void *);
static void call2 (DWORD (*) (void *, void *), void *, void *) __attribute__ ((regparm (3)));
- static struct _threadinfo *find_tls (int sig);
+ static struct _cygtls *find_tls (int sig);
void remove (DWORD);
- void push (__stack_t, bool = false) __attribute__ ((regparm (3)));
+ void push (__stack_t, bool) __attribute__ ((regparm (3)));
__stack_t pop () __attribute__ ((regparm (1)));
bool isinitialized () {return initialized == CYGTLS_INITIALIZED || initialized == CYGTLS_EXCEPTION;}
void set_state (bool);
@@ -138,16 +138,19 @@ struct _threadinfo
void set_siginfo (struct sigpacket *) __attribute__ ((regparm (3)));
void set_threadkill () {threadkill = true;}
void reset_threadkill () {threadkill = false;}
- int lock () __attribute__ ((regparm (1)));
+ int call_signal_handler () __attribute__ ((regparm (1)));
+ void fixup_after_fork () __attribute__ ((regparm (1)));
+ void lock () __attribute__ ((regparm (1)));
void unlock () __attribute__ ((regparm (1)));
+ bool locked () __attribute__ ((regparm (1)));
/*gentls_offsets*/
};
#pragma pack(pop)
extern char *_tlsbase __asm__ ("%fs:4");
extern char *_tlstop __asm__ ("%fs:8");
-#define _my_tls (((_threadinfo *) _tlsbase)[-1])
-extern _threadinfo *_main_tls;
+#define _my_tls (((_cygtls *) _tlsbase)[-1])
+extern _cygtls *_main_tls;
#define __getreent() (&_my_tls.local_clib)
diff --git a/winsup/cygwin/dcrt0.cc b/winsup/cygwin/dcrt0.cc
index f1df888b2..374c901b4 100644
--- a/winsup/cygwin/dcrt0.cc
+++ b/winsup/cygwin/dcrt0.cc
@@ -72,9 +72,9 @@ char NO_COPY **envp;
extern "C" void __sinit (_reent *);
-_threadinfo NO_COPY *_main_tls;
+_cygtls NO_COPY *_main_tls;
-int cygwin_finished_initializing;
+bool NO_COPY cygwin_finished_initializing;
/* Used in SIGTOMASK for generating a bit for insertion into a sigset_t.
This is subtracted from the signal number prior to shifting the bit.
@@ -513,18 +513,16 @@ alloc_stack_hard_way (child_info_fork *ci, volatile char *b)
static void
alloc_stack (child_info_fork *ci)
{
- /* FIXME: adding 16384 seems to avoid a stack copy problem during
- fork on Win95, but I don't know exactly why yet. DJ */
- volatile char b[ci->stacksize + 16384];
-
- if (!VirtualQuery ((LPCVOID) &b, &sm, sizeof sm))
+ if (!VirtualQuery ((LPCVOID) _tlstop, &sm, sizeof sm))
api_fatal ("fork: couldn't get stack info, %E");
if (sm.AllocationBase == ci->stacktop)
- ci->stacksize = 0;
- else
- alloc_stack_hard_way (ci, b + sizeof (b) - 1);
+ {
+ ci->stacksize = 0;
+ return;
+ }
+ alloc_stack_hard_way (ci, b + sizeof (b) - 1);
return;
}
@@ -662,7 +660,6 @@ dll_crt0_0 ()
}
device::init ();
- winpids::init ();
do_global_ctors (&__CTOR_LIST__, 1);
cygthread::init ();
@@ -718,7 +715,7 @@ dll_crt0_0 ()
CloseHandle (child_proc_info->pppid_handle);
}
- _threadinfo::init ();
+ _cygtls::init ();
/* Initialize events */
events_init ();
@@ -873,7 +870,7 @@ dll_crt0_1 (char *)
set_console_title (cp);
}
- cygwin_finished_initializing = 1;
+ cygwin_finished_initializing = true;
/* Call init of loaded dlls. */
dlls.init ();
diff --git a/winsup/cygwin/dll_init.cc b/winsup/cygwin/dll_init.cc
index 72048eff1..a1901a02d 100644
--- a/winsup/cygwin/dll_init.cc
+++ b/winsup/cygwin/dll_init.cc
@@ -371,7 +371,7 @@ dll_dllcrt0 (HMODULE h, per_process *p)
initializing, then the DLL must be a cygwin-aware DLL
that was explicitly linked into the program rather than
a dlopened DLL. */
- if (!cygwin_finished_initializing)
+ if (!in_forkee && !cygwin_finished_initializing)
type = DLL_LINK;
else
{
@@ -387,7 +387,7 @@ dll_dllcrt0 (HMODULE h, per_process *p)
initialize the DLL. If we haven't finished initializing,
it may not be safe to call the dll's "main" since not
all of cygwin's internal structures may have been set up. */
- if (!d || (cygwin_finished_initializing && !d->init ()))
+ if (!d || ((in_forkee || cygwin_finished_initializing) && !d->init ()))
return -1;
return (DWORD) d;
diff --git a/winsup/cygwin/exceptions.cc b/winsup/cygwin/exceptions.cc
index 03df67f10..490756544 100644
--- a/winsup/cygwin/exceptions.cc
+++ b/winsup/cygwin/exceptions.cc
@@ -519,7 +519,7 @@ handle_exceptions (EXCEPTION_RECORD *e0, void *frame, CONTEXT *in0, void *)
break;
}
- if (!myself->progname[0]
+ if (!cygwin_finished_initializing
|| GetCurrentThreadId () == sigtid
|| (void *) global_sigs[si.si_signo].sa_handler == (void *) SIG_DFL
|| (void *) global_sigs[si.si_signo].sa_handler == (void *) SIG_IGN
@@ -692,10 +692,10 @@ interruptible (DWORD pc)
return res;
}
void __stdcall
-_threadinfo::interrupt_setup (int sig, void *handler,
+_cygtls::interrupt_setup (int sig, void *handler,
struct sigaction& siga)
{
- push ((__stack_t) sigdelayed);
+ push ((__stack_t) sigdelayed, false);
oldmask = myself->getsigmask ();
newmask = oldmask | siga.sa_mask | SIGTOMASK (sig);
sa_flags = siga.sa_flags;
@@ -717,28 +717,16 @@ _threadinfo::interrupt_setup (int sig, void *handler,
}
bool
-_threadinfo::interrupt_now (CONTEXT *ctx, int sig, void *handler,
+_cygtls::interrupt_now (CONTEXT *ctx, int sig, void *handler,
struct sigaction& siga)
{
- push ((__stack_t) ctx->Eip);
+ push ((__stack_t) ctx->Eip, false);
interrupt_setup (sig, handler, siga);
ctx->Eip = pop ();
SetThreadContext (*this, ctx); /* Restart the thread in a new location */
return 1;
}
-void __stdcall
-signal_fixup_after_fork ()
-{
- if (_my_tls.sig)
- {
- _my_tls.sig = 0;
- _my_tls.stackptr = _my_tls.stack + 1; // FIXME?
- set_signal_mask (_my_tls.oldmask);
- }
- sigproc_init ();
-}
-
extern "C" void __stdcall
set_sig_errno (int e)
{
@@ -747,13 +735,14 @@ set_sig_errno (int e)
// sigproc_printf ("errno %d", e);
}
-static int setup_handler (int, void *, struct sigaction&, _threadinfo *tls)
+static int setup_handler (int, void *, struct sigaction&, _cygtls *tls)
__attribute__((regparm(3)));
static int
-setup_handler (int sig, void *handler, struct sigaction& siga, _threadinfo *tls)
+setup_handler (int sig, void *handler, struct sigaction& siga, _cygtls *tls)
{
CONTEXT cx;
bool interrupted = false;
+ bool locked = false;
if (tls->sig)
{
@@ -762,12 +751,11 @@ setup_handler (int sig, void *handler, struct sigaction& siga, _threadinfo *tls)
goto out;
}
- int locked;
for (int i = 0; i < CALL_HANDLER_RETRY; i++)
{
- locked = tls->lock ();
- __stack_t *retaddr_on_stack = tls->stackptr - 1;
- if (retaddr_on_stack >= tls->stack)
+ tls->lock ();
+ locked = true;
+ if (tls->stackptr > tls->stack)
{
tls->reset_exception ();
tls->interrupt_setup (sig, handler, siga);
@@ -776,14 +764,14 @@ setup_handler (int sig, void *handler, struct sigaction& siga, _threadinfo *tls)
break;
}
+ tls->unlock ();
+ locked = false;
DWORD res;
HANDLE hth = (HANDLE) *tls;
- /* Suspend the thread which will receive the signal. But first ensure that
- this thread doesn't have any mutos. (FIXME: Someday we should just grab
- all of the mutos rather than checking for them)
- For Windows 95, we also have to ensure that the addresses returned by GetThreadContext
- are valid.
+ /* Suspend the thread which will receive the signal.
+ For Windows 95, we also have to ensure that the addresses returned by
+ GetThreadContext are valid.
If one of these conditions is not true we loop for a fixed number of times
since we don't want to stall the signal handler. FIXME: Will this result in
noticeable delays?
@@ -799,31 +787,25 @@ setup_handler (int sig, void *handler, struct sigaction& siga, _threadinfo *tls)
sigproc_printf ("suspending mainthread PC %p", cx.Eip);
#endif
res = SuspendThread (hth);
- /* Just release the lock now since we hav suspended the main thread and it
- definitely can't be grabbing it now. This will have to change, of course,
- if/when we can send signals to other than the main thread. */
-
/* Just set pending if thread is already suspended */
if (res)
{
(void) ResumeThread (hth);
break;
}
-
- // FIXME - add check for reentering of DLL here
-
- cx.ContextFlags = CONTEXT_CONTROL | CONTEXT_INTEGER;
- if (!GetThreadContext (hth, &cx))
- system_printf ("couldn't get context of main thread, %E");
- else if (interruptible (cx.Eip))
- interrupted = tls->interrupt_now (&cx, sig, handler, siga);
+ if (!tls->locked ())
+ {
+ cx.ContextFlags = CONTEXT_CONTROL | CONTEXT_INTEGER;
+ if (!GetThreadContext (hth, &cx))
+ system_printf ("couldn't get context of main thread, %E");
+ else if (interruptible (cx.Eip))
+ interrupted = tls->interrupt_now (&cx, sig, handler, siga);
+ }
res = ResumeThread (hth);
if (interrupted)
break;
- tls->unlock ();
- locked = false;
sigproc_printf ("couldn't interrupt. trying again.");
low_priority_sleep (0);
}
@@ -845,6 +827,10 @@ static BOOL WINAPI
ctrl_c_handler (DWORD type)
{
static bool saw_close;
+
+ if (!cygwin_finished_initializing)
+ ExitProcess (STATUS_CONTROL_C_EXIT);
+
_my_tls.remove (INFINITE);
/* Return FALSE to prevent an "End task" dialog box from appearing
@@ -977,7 +963,7 @@ sigpacket::process ()
/* nothing to do */;
else if (tls && sigismember (&tls->sigwait_mask, si.si_signo))
insigwait_mask = true;
- else if (!tls && (tls = _threadinfo::find_tls (si.si_signo)))
+ else if (!tls && (tls = _cygtls::find_tls (si.si_signo)))
insigwait_mask = true;
else if (!(masked = sigismember (mask, si.si_signo)) && tls)
masked = sigismember (&tls->sigmask, si.si_signo);
@@ -1153,36 +1139,36 @@ events_terminate (void)
exit_already = 1;
}
-extern "C" {
-int __stdcall
-call_signal_handler_now ()
+int
+_cygtls::call_signal_handler ()
{
- int sa_flags = 0;
- while (_my_tls.sig && _my_tls.stackptr > _my_tls.stack)
+ int this_sa_flags = 0;
+ /* Call signal handler. No need to set stacklock since sig effectively
+ implies that. */
+ while (sig)
{
- sa_flags = _my_tls.sa_flags;
- int sig = _my_tls.sig;
- void (*sigfunc) (int) = _my_tls.func;
+ this_sa_flags = sa_flags;
+ int thissig = sig;
+ void (*sigfunc) (int) = func;
- (void) _my_tls.pop ();
+ (void) pop ();
reset_signal_arrived ();
- sigset_t oldmask = _my_tls.oldmask;
- int this_errno = _my_tls.saved_errno;
- set_process_mask (_my_tls.newmask);
- _my_tls.sig = 0;
- sigfunc (sig);
+ sigset_t oldmask = oldmask;
+ int this_errno = saved_errno;
+ set_process_mask (newmask);
+ sig = 0;
+ sigfunc (thissig);
set_process_mask (oldmask);
if (this_errno >= 0)
set_errno (this_errno);
}
- return sa_flags & SA_RESTART;
+ return this_sa_flags & SA_RESTART;
}
-void __stdcall
+extern "C" void __stdcall
reset_signal_arrived ()
{
(void) ResetEvent (signal_arrived);
sigproc_printf ("reset signal_arrived");
}
-}
diff --git a/winsup/cygwin/fork.cc b/winsup/cygwin/fork.cc
index 8a5e5bfa0..01b9dbc23 100644
--- a/winsup/cygwin/fork.cc
+++ b/winsup/cygwin/fork.cc
@@ -167,11 +167,11 @@ sync_with_child (PROCESS_INFORMATION &pi, HANDLE subproc_ready,
*/
if (errcode != STATUS_CONTROL_C_EXIT)
{
- system_printf ("child %u(%p) died before initialization with status code %p",
- cygwin_pid (pi.dwProcessId), pi.hProcess, errcode);
- system_printf ("*** child state %s", s);
+ system_printf ("child %u(%p) died before initialization with status code %p",
+ cygwin_pid (pi.dwProcessId), pi.hProcess, errcode);
+ system_printf ("*** child state %s", s);
#ifdef DEBUGGING
- abort ();
+ try_to_debug ();
#endif
}
set_errno (EAGAIN);
@@ -212,13 +212,13 @@ sync_with_parent (const char *s, bool hang_self)
switch (psync_rc)
{
case WAIT_TIMEOUT:
- api_fatal ("WFSO timed out for %s", s);
+ api_fatal ("WFSO timed out %s", s);
break;
case WAIT_FAILED:
if (GetLastError () == ERROR_INVALID_HANDLE &&
WaitForSingleObject (fork_info->forker_finished, 1) != WAIT_FAILED)
break;
- api_fatal ("WFSO failed for %s, fork_finished %p, %E", s,
+ api_fatal ("WFSO failed %s, fork_finished %p, %E", s,
fork_info->forker_finished);
break;
default:
@@ -243,6 +243,17 @@ fork_child (HANDLE& hParent, dll *&first_dll, bool& load_dlls)
sigproc_printf ("hParent %p, child 1 first_dll %p, load_dlls %d", hParent,
first_dll, load_dlls);
+ /* If we've played with the stack, stacksize != 0. That means that
+ fork() was invoked from other than the main thread. Make sure that
+ the threadinfo information is properly set up. */
+ if (!fork_info->stacksize)
+ {
+ _main_tls = &_my_tls;
+ _main_tls->init_thread (NULL, NULL);
+ _main_tls->local_clib = *_impure_ptr;
+ _impure_ptr = &_main_tls->local_clib;
+ }
+
#ifdef DEBUGGING
char c;
if (GetEnvironmentVariable ("FORKDEBUG", &c, 1))
@@ -257,18 +268,6 @@ fork_child (HANDLE& hParent, dll *&first_dll, bool& load_dlls)
}
#endif
- /* If we've played with the stack, stacksize != 0. That means that
- fork() was invoked from other than the main thread. Make sure that
- when the "main" thread exits it calls do_exit, like a normal process.
- Exit with a status code of 0. */
- if (fork_info->stacksize)
- {
- _main_tls = &_my_tls;
- _main_tls->init_thread (NULL, NULL);
- _main_tls->local_clib = *_impure_ptr;
- _impure_ptr = &_main_tls->local_clib;
- }
-
set_file_api_mode (current_codepage);
MALLOC_CHECK;
@@ -307,7 +306,8 @@ fork_child (HANDLE& hParent, dll *&first_dll, bool& load_dlls)
#endif
pinfo_fixup_after_fork ();
- signal_fixup_after_fork ();
+ _my_tls.fixup_after_fork ();
+ sigproc_init ();
/* Set thread local stuff to zero. Under Windows 95/98 this is sometimes
non-zero, for some reason.
@@ -320,6 +320,7 @@ fork_child (HANDLE& hParent, dll *&first_dll, bool& load_dlls)
fixup_timers_after_fork ();
wait_for_sigthread ();
cygbench ("fork-child");
+ cygwin_finished_initializing = true;
return 0;
}
@@ -458,7 +459,7 @@ fork_parent (HANDLE& hParent, dll *&first_dll,
syscall_printf ("CreateProcess (%s, %s, 0, 0, 1, %x, 0, 0, %p, %p)",
myself->progname, myself->progname, c_flags, &si, &pi);
- __malloc_lock ();
+ bool locked = __malloc_lock ();
void *newheap;
newheap = cygheap_setup_for_child (&ch, cygheap->fdtab.need_fixup_before ());
rc = CreateProcess (myself->progname, /* image to run */
@@ -483,6 +484,7 @@ fork_parent (HANDLE& hParent, dll *&first_dll,
/* Restore impersonation */
cygheap->user.reimpersonate ();
cygheap_setup_for_child_cleanup (newheap, &ch, 0);
+ __malloc_unlock ();
return -1;
}
@@ -573,6 +575,7 @@ fork_parent (HANDLE& hParent, dll *&first_dll,
dll_bss_start, dll_bss_end, impure_beg, impure_end, NULL);
__malloc_unlock ();
+ locked = false;
MALLOC_CHECK;
if (!rc)
goto cleanup;
@@ -622,6 +625,9 @@ fork_parent (HANDLE& hParent, dll *&first_dll,
/* Common cleanup code for failure cases */
cleanup:
+ if (locked)
+ __malloc_unlock ();
+
/* Remember to de-allocate the fd table. */
if (pi.hProcess)
ForceCloseHandle1 (pi.hProcess, childhProc);
@@ -725,7 +731,7 @@ vfork ()
debug_printf ("cygheap->ctty_on_hold %p, cygheap->open_fhs %d", cygheap->ctty_on_hold, cygheap->open_fhs);
int res = cygheap->fdtab.vfork_child_dup () ? 0 : -1;
debug_printf ("%d = vfork()", res);
- call_signal_handler_now (); // FIXME: racy
+ _my_tls.call_signal_handler (); // FIXME: racy
vf->tls = _my_tls;
return res;
}
@@ -757,7 +763,7 @@ vfork ()
debug_printf ("exiting vfork, pid %d", pid);
sig_dispatch_pending ();
- call_signal_handler_now (); // FIXME: racy
+ _my_tls.call_signal_handler (); // FIXME: racy
_my_tls = vf->tls;
return pid;
#endif
diff --git a/winsup/cygwin/gendef b/winsup/cygwin/gendef
index b391d501e..72afbc1c9 100755
--- a/winsup/cygwin/gendef
+++ b/winsup/cygwin/gendef
@@ -91,86 +91,99 @@ EOF
.stabs "_sigfe:F(0,1)",36,0,0,__sigbe
__sigfe:
+ pushl %ebx
pushl %edx
- movl %fs:4,%edx
-1: movl \$1,%eax
- lock xchgl %eax,$tls::stacklock(%edx)
- cmpl %eax,%eax
- jz 2f
- xorl %eax,%eax
- call _low_priority_sleep
- jmp 1b
-2: movl \$4,%eax
- xadd %eax,$tls::stackptr(%edx)
- decl $tls::stacklock(%edx)
- leal __sigbe,%edx
- xchgl %edx,8(%esp)
- movl %edx,(%eax)
- popl %edx
+1: movl %fs:4,%edx # location of bottom of stack
+ movl \$1,%eax # potential lock value
+ lock xchgl %eax,$tls::stacklock(%edx) # see if we can grab it
+ orl %eax,%eax # it will be zero
+ jz 2f # if so
+ xorl %eax,%eax # nope. It was not zero
+ call _low_priority_sleep # should be a short-time thing, so
+ jmp 1b # sleep and loop
+2: movl \$4,%eax # have the lock, now increment the
+ xadd %eax,$tls::stackptr(%edx) # stack pointer and get pointer
+ leal __sigbe,%ebx # new place to return to
+ xchgl %ebx,12(%esp) # exchange with real return value
+ movl %ebx,(%eax) # store real return value on alt stack
+ decl $tls::stacklock(%edx) # remove lock
+ popl %edx # restore saved value
+ popl %ebx
ret
.global __sigbe
.stabs "_sigbe:F(0,1)",36,0,0,__sigbe
__sigbe:
- pushl %edx
- pushl %eax
- movl %fs:4,%edx
-1: movl \$1,%eax
- lock xchgl %eax,$tls::stacklock(%edx)
- cmpl %eax,%eax
- jz 2f
- xorl %eax,%eax
- call _low_priority_sleep
- jmp 1b
-2: movl \$-4,%eax
- xadd %eax,$tls::stackptr(%edx)
- decl $tls::stacklock(%edx)
- xchgl %edx,-4(%eax)
- xchgl %edx,4(%esp)
+ pushl %ebx
+ pushl %edx # return here after cygwin syscall
+ pushl %eax # don't clobber
+1: movl %fs:4,%edx # address of bottom of tls
+ movl \$1,%eax # potential lock value
+ lock xchgl %eax,$tls::stacklock(%edx) # see if we can grab it
+ orl %eax,%eax # it will be zero
+ jz 2f # if so
+ xorl %eax,%eax # nope. not zero
+ call _low_priority_sleep # sleep
+ jmp 1b # and loop
+2: movl \$-4,%eax # now decrement aux stack
+ xadd %eax,$tls::stackptr(%edx) # and get pointer
+# xorl %ebx,%ebx
+ movl \$0x41774177,%ebx
+ xchgl %ebx,-4(%eax) #
+ xchgl %ebx,8(%esp)
+ decl $tls::stacklock(%edx) # release lock
popl %eax
+ popl %edx
ret
- .global __ZN11_threadinfo3popEv
-__ZN11_threadinfo3popEv:
+ .global __ZN7_cygtls3popEv
+__ZN7_cygtls3popEv:
1: pushl %ebx
+ pushl %edx # FIXME: needed?
movl %eax,%edx
movl \$-4,%ebx
xadd %ebx,$tls::pstackptr(%edx)
- xorl %eax,%eax
+# xorl %eax,%eax
+ movl 8(%esp),%eax
xchgl %eax,-4(%ebx)
+ popl %edx # FIXME: needed?
popl %ebx
ret
- .global __ZN11_threadinfo4lockEv
-__ZN11_threadinfo4lockEv:
- pushl %ebx
- movl %eax,%ebx
+ .global __ZN7_cygtls4lockEv
+__ZN7_cygtls4lockEv:
+ pushl %edi
+ movl %eax,%edi
1: movl \$1,%eax
- lock xchgl %eax,$tls::pstacklock(%ebx)
- cmpl %eax,%eax
+ lock xchgl %eax,$tls::pstacklock(%edi)
+ orl %eax,%eax
jz 2f
xorl %eax,%eax
call _low_priority_sleep
jmp 1b
-2: xorl \$1,%eax
- popl %ebx
+2: popl %edi
ret
- .global __ZN11_threadinfo6unlockEv
-__ZN11_threadinfo6unlockEv:
+ .global __ZN7_cygtls6unlockEv
+__ZN7_cygtls6unlockEv:
decl $tls::pstacklock(%eax)
ret
+ .global __ZN7_cygtls6lockedEv
+__ZN7_cygtls6lockedEv:
+ movl $tls::pstacklock(%eax),%eax
+ ret
+
.global _sigreturn
.stabs "sigreturn:F(0,1)",36,0,0,_sigreturn
_sigreturn:
- addl \$4,%esp # Remove argument
+ addl \$4,%esp # Remove argument
call _set_process_mask\@4
movl %fs:4,%ebx
- cmpl \$0,$tls::sig(%ebx) # Did a signal come in?
- jnz 3f # Yes, if non-zero
+# cmpl \$0,$tls::sig(%ebx) # Did a signal come in?
+# jnz 3f # Yes, if non-zero
1: popl %edx # saved errno
testl %edx,%edx # Is it < 0
@@ -215,8 +228,7 @@ _sigdelayed:
movl \$0,$tls::sig(%ebx) # zero the signal number as a
# flag to the signal handler thread
# that it is ok to set up sigsave
-4: popl %ebx
- jmp *%ebx
+4: ret
EOF
}
@@ -229,15 +241,26 @@ sub longjmp {
.globl _longjmp
_longjmp:
+1: movl %fs:4,%edx
+ movl \$1,%eax
+ lock xchgl %eax,$tls::stacklock(%edx)
+ orl %eax,%eax
+ jz 2f
+ xorl %eax,%eax
+ call _low_priority_sleep
+ jmp 1b
+2: leal ($tls::stack)(%edx),%eax
+ movl %eax,($tls::stackptr)(%edx)
+
pushl %ebp
movl %esp,%ebp
movl 8(%ebp),%edi
movl 12(%ebp),%eax
testl %eax,%eax
- jne 0f
+ jne 3f
incl %eax
-0:
- movl %eax,0(%edi)
+
+3: movl %eax,0(%edi)
movl 24(%edi),%ebp
pushfl
popl %ebx
@@ -250,14 +273,12 @@ _longjmp:
movw %ax,%es
movw 40(%edi),%ax
movw %ax,%gs
- movl %fs:4,%eax
- leal ($tls::stack)(%eax),%edx
- movl %edx,($tls::stackptr)(%eax)
movl 0(%edi),%eax
movl 4(%edi),%ebx
movl 8(%edi),%ecx
- movl 12(%edi),%edx
movl 16(%edi),%esi
+ decl $tls::stacklock(%edx)
+ movl 12(%edi),%edx
movl 20(%edi),%edi
popfl
ret
diff --git a/winsup/cygwin/init.cc b/winsup/cygwin/init.cc
index 7ad38f11b..8bbc89bfb 100644
--- a/winsup/cygwin/init.cc
+++ b/winsup/cygwin/init.cc
@@ -27,7 +27,7 @@ HANDLE sync_startup;
static void WINAPI
threadfunc_fe (VOID *arg)
{
- _threadinfo::call ((DWORD (*) (void *, void *)) (((char **) _tlsbase)[OLDFUNC_OFFSET]), arg);
+ _cygtls::call ((DWORD (*) (void *, void *)) (((char **) _tlsbase)[OLDFUNC_OFFSET]), arg);
}
static DWORD WINAPI
diff --git a/winsup/cygwin/miscfuncs.cc b/winsup/cygwin/miscfuncs.cc
index 37ef3a49c..4207c4d1a 100644
--- a/winsup/cygwin/miscfuncs.cc
+++ b/winsup/cygwin/miscfuncs.cc
@@ -318,7 +318,7 @@ low_priority_sleep (DWORD secs)
if (!secs && wincap.has_switch_to_thread ())
{
- for (int i = 0; i < 10; i++)
+ for (int i = 0; i < 3; i++)
SwitchToThread ();
}
else
diff --git a/winsup/cygwin/perthread.h b/winsup/cygwin/perthread.h
index c721cefea..429b7cac9 100644
--- a/winsup/cygwin/perthread.h
+++ b/winsup/cygwin/perthread.h
@@ -58,7 +58,7 @@ class vfork_save
public:
int pid;
DWORD frame[100];
- _threadinfo tls;
+ _cygtls tls;
char **vfork_ebp;
char **vfork_esp;
int ctty;
diff --git a/winsup/cygwin/pinfo.cc b/winsup/cygwin/pinfo.cc
index e3723f863..a9a0b80e7 100644
--- a/winsup/cygwin/pinfo.cc
+++ b/winsup/cygwin/pinfo.cc
@@ -30,6 +30,7 @@ details. */
#include "shared_info.h"
#include "cygheap.h"
#include "fhandler.h"
+#include "cygmalloc.h"
static char NO_COPY pinfo_dummy[sizeof (_pinfo)] = {0};
@@ -755,22 +756,14 @@ winpids::enum9x (bool winpid)
return nelem;
}
-NO_COPY CRITICAL_SECTION winpids::cs;
-
void
winpids::set (bool winpid)
{
- EnterCriticalSection (&cs);
+ __malloc_lock ();
npids = (this->*enum_processes) (winpid);
if (pidlist)
pidlist[npids] = 0;
- LeaveCriticalSection (&cs);
-}
-
-void
-winpids::init ()
-{
- InitializeCriticalSection (&cs);
+ __malloc_unlock ();
}
DWORD
diff --git a/winsup/cygwin/pinfo.h b/winsup/cygwin/pinfo.h
index b0ddb6702..923b0bec7 100644
--- a/winsup/cygwin/pinfo.h
+++ b/winsup/cygwin/pinfo.h
@@ -179,7 +179,6 @@ class winpids
DWORD enumNT (bool winpid);
DWORD enum9x (bool winpid);
void add (DWORD& nelem, bool, DWORD pid);
- static CRITICAL_SECTION cs;
public:
DWORD npids;
inline void reset () { npids = 0; release (); }
@@ -196,7 +195,6 @@ public:
inline _pinfo *operator [] (int i) const {return (_pinfo *) pinfolist[i];}
~winpids ();
void release ();
- static void init ();
};
extern __inline pid_t
diff --git a/winsup/cygwin/signal.cc b/winsup/cygwin/signal.cc
index 54232bb45..b0ac94a79 100644
--- a/winsup/cygwin/signal.cc
+++ b/winsup/cygwin/signal.cc
@@ -93,7 +93,7 @@ nanosleep (const struct timespec *rqtp, struct timespec *rmtp)
rem = 0;
if (rc == WAIT_OBJECT_0)
{
- (void) call_signal_handler_now ();
+ (void) _my_tls.call_signal_handler ();
set_errno (EINTR);
res = -1;
}
@@ -302,7 +302,7 @@ kill_pgrp (pid_t pid, siginfo_t& si)
found++;
}
- if (killself && kill_worker (myself->pid, si))
+ if (killself && !exit_state && kill_worker (myself->pid, si))
res = -1;
if (!found)
@@ -341,7 +341,7 @@ abort (void)
set_signal_mask (sig_mask);
raise (SIGABRT);
- (void) call_signal_handler_now (); /* Call any signal handler */
+ (void) _my_tls.call_signal_handler (); /* Call any signal handler */
do_exit (1); /* signal handler didn't exit. Goodbye. */
}
diff --git a/winsup/cygwin/sigproc.cc b/winsup/cygwin/sigproc.cc
index caa22a5a9..c013e0d20 100644
--- a/winsup/cygwin/sigproc.cc
+++ b/winsup/cygwin/sigproc.cc
@@ -668,7 +668,7 @@ sig_send (_pinfo *p, int sig)
If sending to this process, wait for notification that a signal has
completed before returning. */
int __stdcall
-sig_send (_pinfo *p, siginfo_t& si, _threadinfo *tls)
+sig_send (_pinfo *p, siginfo_t& si, _cygtls *tls)
{
int rc = 1;
bool its_me;
@@ -747,7 +747,7 @@ sig_send (_pinfo *p, siginfo_t& si, _threadinfo *tls)
if (!pack.si.si_uid)
pack.si.si_uid = myself->uid;
pack.pid = myself->pid;
- pack.tls = (_threadinfo *) tls;
+ pack.tls = (_cygtls *) tls;
if (wait_for_completion)
{
pack.wakeup = CreateEvent (&sec_none_nih, FALSE, FALSE, NULL);
@@ -816,7 +816,7 @@ sig_send (_pinfo *p, siginfo_t& si, _threadinfo *tls)
}
if (wait_for_completion && si.si_signo != __SIGFLUSHFAST)
- call_signal_handler_now ();
+ _my_tls.call_signal_handler ();
out:
if (pack.wakeup)
diff --git a/winsup/cygwin/sigproc.h b/winsup/cygwin/sigproc.h
index e9c762112..1176c919c 100644
--- a/winsup/cygwin/sigproc.h
+++ b/winsup/cygwin/sigproc.h
@@ -54,7 +54,7 @@ struct sigpacket
{
siginfo_t si;
pid_t pid;
- class _threadinfo *tls;
+ class _cygtls *tls;
sigset_t *mask;
union
{
@@ -91,9 +91,8 @@ void __stdcall subproc_init ();
void __stdcall sigproc_terminate ();
bool __stdcall proc_exists (_pinfo *) __attribute__ ((regparm(1)));
bool __stdcall pid_exists (pid_t) __attribute__ ((regparm(1)));
-int __stdcall sig_send (_pinfo *, siginfo_t&, class _threadinfo *tls = NULL) __attribute__ ((regparm (3)));
+int __stdcall sig_send (_pinfo *, siginfo_t&, class _cygtls *tls = NULL) __attribute__ ((regparm (3)));
int __stdcall sig_send (_pinfo *, int) __attribute__ ((regparm (2)));
-void __stdcall signal_fixup_after_fork ();
void __stdcall signal_fixup_after_exec ();
void __stdcall wait_for_sigthread ();
void __stdcall sigalloc ();
diff --git a/winsup/cygwin/sync.cc b/winsup/cygwin/sync.cc
index 2116ed0a8..f65e5a8e1 100644
--- a/winsup/cygwin/sync.cc
+++ b/winsup/cygwin/sync.cc
@@ -69,8 +69,10 @@ int
muto::acquire (DWORD ms)
{
DWORD this_tid = GetCurrentThreadId ();
+#if 0
if (exiting_thread)
return this_tid == exiting_thread;
+#endif
if (tid != this_tid)
{
@@ -113,8 +115,6 @@ int
muto::release ()
{
DWORD this_tid = GetCurrentThreadId ();
- if (exiting_thread)
- return this_tid == exiting_thread;
if (tid != this_tid || !visits)
{
diff --git a/winsup/cygwin/syscalls.cc b/winsup/cygwin/syscalls.cc
index 790fcb82b..ccf5848ca 100644
--- a/winsup/cygwin/syscalls.cc
+++ b/winsup/cygwin/syscalls.cc
@@ -461,7 +461,7 @@ readv (int fd, const struct iovec *const iov, const int iovcnt)
}
out:
- if (res >= 0 || get_errno () != EINTR || !call_signal_handler_now ())
+ if (res >= 0 || get_errno () != EINTR || !_my_tls.call_signal_handler ())
break;
set_errno (e);
}
diff --git a/winsup/cygwin/termios.cc b/winsup/cygwin/termios.cc
index e046984b6..c33054af5 100644
--- a/winsup/cygwin/termios.cc
+++ b/winsup/cygwin/termios.cc
@@ -23,6 +23,7 @@ details. */
#include "cygwin/version.h"
#include "perprocess.h"
#include "sigproc.h"
+#include "cygtls.h"
#include <sys/termios.h>
/* tcsendbreak: POSIX 7.2.2.1 */
@@ -146,7 +147,7 @@ tcsetattr (int fd, int a, const struct termios *t)
e = get_errno ();
break;
case bg_signalled:
- if (call_signal_handler_now ())
+ if (_my_tls.call_signal_handler ())
continue;
res = -1;
/* fall through intentionally */
diff --git a/winsup/cygwin/thread.h b/winsup/cygwin/thread.h
index 361981777..7d68b5f5f 100644
--- a/winsup/cygwin/thread.h
+++ b/winsup/cygwin/thread.h
@@ -348,7 +348,7 @@ private:
#define WAIT_CANCELED (WAIT_OBJECT_0 + 1)
-class _threadinfo;
+class _cygtls;
class pthread: public verifyable_object
{
public:
@@ -360,7 +360,7 @@ public:
bool valid;
bool suspended;
int cancelstate, canceltype;
- _threadinfo *cygtls;
+ _cygtls *cygtls;
HANDLE cancel_event;
pthread_t joiner;
diff --git a/winsup/cygwin/wait.cc b/winsup/cygwin/wait.cc
index 8e5800b63..d92a32911 100644
--- a/winsup/cygwin/wait.cc
+++ b/winsup/cygwin/wait.cc
@@ -15,6 +15,7 @@ details. */
#include "sigproc.h"
#include "perthread.h"
#include "thread.h"
+#include "cygtls.h"
/* This is called _wait and not wait because the real wait is defined
in libc/syscalls/syswait.c. It calls us. */
@@ -99,7 +100,7 @@ wait4 (int intpid, int *status, int options, struct rusage *r)
if (w->status == -1)
{
set_sig_errno (EINTR);
- call_signal_handler_now ();
+ _my_tls.call_signal_handler ();
sawsig = true;
res = -1;
}
@@ -114,7 +115,7 @@ wait4 (int intpid, int *status, int options, struct rusage *r)
*status = w->status;
done:
- if (!sawsig || !call_signal_handler_now ())
+ if (!sawsig || !_my_tls.call_signal_handler ())
break;
}
diff --git a/winsup/cygwin/winsup.h b/winsup/cygwin/winsup.h
index 9301e92b1..d8930f9c6 100644
--- a/winsup/cygwin/winsup.h
+++ b/winsup/cygwin/winsup.h
@@ -239,7 +239,7 @@ extern "C" int try_to_debug (bool waitloop = 1);
void set_file_api_mode (codepage_type);
-extern int cygwin_finished_initializing;
+extern bool cygwin_finished_initializing;
/**************************** Miscellaneous ******************************/