diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index f1a607580..b4716ee36 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,20 @@ +2005-09-22 Christopher Faylor + + * cygheap.cc (cygheap_fixup_in_child): It's not just for exec. + * cygtls.h (struct _cygtls::thread_handle): New field. + * dcrt0.cc (exit_lock): Remove declaration. + * winsup.h (exit_lock): Add declaration. + * exceptions.cc (sigpacket::process): Properly return after + signal_exit. + * pinfo.cc (pinfo::exit): Only exit the process if + _my_tls.thread_handle has not been filled out -- which should be an + impossible event. + * sigproc.cc (sigproc_terminate): Fillout _my_tls.thread_handle to + provide something for wait_sig to wait for. Use the siginfo_t version + of sig_send and fill out the tls argument with _my_tls. + (wait_sig): Wait for the thread specified in pack.tls or (for now) + complain bitterly if it doesn't exit. + 2005-09-22 Christopher Faylor * pinfo.cc (set_myself): Call strace.hello unconditionally when diff --git a/winsup/cygwin/cygheap.cc b/winsup/cygwin/cygheap.cc index fff2ad0d2..6cbdf6ef7 100644 --- a/winsup/cygwin/cygheap.cc +++ b/winsup/cygwin/cygheap.cc @@ -59,7 +59,7 @@ cygheap_fixup_in_child (bool execed) cygheap_max = child_proc_info->cygheap; cygheap = (init_cygheap *) cygheap_max; _csbrk ((char *) child_proc_info->cygheap_max - (char *) cygheap); - child_copy (child_proc_info->parent, child_proc_info->dwProcessId, "cygheap for exec", cygheap, cygheap_max); + child_copy (child_proc_info->parent, child_proc_info->dwProcessId, "cygheap", cygheap, cygheap_max); cygheap_init (); debug_fixup_after_fork_exec (); diff --git a/winsup/cygwin/cygtls.h b/winsup/cygwin/cygtls.h index 33ffccb2f..9bffe8f88 100644 --- a/winsup/cygwin/cygtls.h +++ b/winsup/cygwin/cygtls.h @@ -176,14 +176,15 @@ struct _cygtls siginfo_t infodata; struct pthread *tid; union - { - struct _reent local_clib; - char __dontuse[8 * ((sizeof(struct _reent) + 4) / 8)]; - }; + { + struct _reent local_clib; + char __dontuse[8 * ((sizeof(struct _reent) + 4) / 8)]; + }; struct _local_storage locals; class cygthread *_ctinfo; san andreas; waitq wq; + HANDLE thread_handle; struct _cygtls *prev, *next; __stack_t *stackptr; int sig; diff --git a/winsup/cygwin/dcrt0.cc b/winsup/cygwin/dcrt0.cc index 39dd08c13..ca8b601c9 100644 --- a/winsup/cygwin/dcrt0.cc +++ b/winsup/cygwin/dcrt0.cc @@ -998,7 +998,6 @@ __main (void) } exit_states NO_COPY exit_state; -extern CRITICAL_SECTION exit_lock; void __stdcall do_exit (int status) diff --git a/winsup/cygwin/exceptions.cc b/winsup/cygwin/exceptions.cc index efd49ce6f..79cc251a3 100644 --- a/winsup/cygwin/exceptions.cc +++ b/winsup/cygwin/exceptions.cc @@ -1162,6 +1162,7 @@ exit_sig: sigproc_printf ("signal %d, about to call do_exit", si.si_signo); signal_exit (si.si_signo); /* May not return */ + return rc; } CRITICAL_SECTION NO_COPY exit_lock; diff --git a/winsup/cygwin/pinfo.cc b/winsup/cygwin/pinfo.cc index 78964a486..1d7b837cb 100644 --- a/winsup/cygwin/pinfo.cc +++ b/winsup/cygwin/pinfo.cc @@ -140,6 +140,7 @@ pinfo::zap_cwd () void pinfo::exit (DWORD n) { + EnterCriticalSection (&exit_lock); cygthread::terminate (); if (n != EXITCODE_NOSET) self->exitcode = EXITCODE_SET | n;/* We're really exiting. Record the UNIX exit code. */ @@ -152,7 +153,7 @@ pinfo::exit (DWORD n) sigproc_terminate (ES_FINAL); /* FIXME: There is a potential race between an execed process and its - parent here. I hated to add a mutex just for this, though. */ + parent here. I hated to add a mutex just for that, though. */ struct rusage r; fill_rusage (&r, hMainProc); add_rusage (&self->rusage_self, &r); @@ -169,27 +170,16 @@ pinfo::exit (DWORD n) _my_tls.stacklock = 0; _my_tls.stackptr = _my_tls.stack; - if (&_my_tls == _main_tls) + if (_my_tls.thread_handle) { sigproc_printf ("Calling ExitThread hProcess %p, n %p, exitcode %p", hProcess, n, exitcode); ExitThread (exitcode); } - else if (hMainThread) - { -#if 0 /* This would be nice, but I don't think that Windows guarantees that - TerminateThread will not block. */ - sigproc_printf ("Calling TerminateThread since %p != %p, %p, n %p, exitcode %p", - &_my_tls, _main_tls, hProcess, n, exitcode); - TerminateThread (hMainThread, exitcode); - if (&_my_tls != _sig_tls) - ExitThread (0); -#endif - } sigproc_printf ("Calling ExitProcess since hMainthread is 0, hProcess %p, n %p, exitcode %p", hProcess, n, exitcode); - // release (); Could race with signal thread. Sigh. + release (); ExitProcess (exitcode); } # undef self diff --git a/winsup/cygwin/sigproc.cc b/winsup/cygwin/sigproc.cc index b9c66f376..8d84551eb 100644 --- a/winsup/cygwin/sigproc.cc +++ b/winsup/cygwin/sigproc.cc @@ -497,7 +497,15 @@ sigproc_terminate (exit_states es) else { sigproc_printf ("entering"); - sig_send (myself_nowait, __SIGEXIT); + siginfo_t si; + memset (&si, 0, sizeof (si)); + si.si_signo = __SIGEXIT; + if (&_my_tls == _main_tls) + _my_tls.thread_handle = hMainThread; + else + DuplicateHandle (hMainProc, GetCurrentThread (), hMainProc, &_my_tls.thread_handle, 0, + FALSE, DUPLICATE_SAME_ACCESS); + sig_send (myself_nowait, si, &_my_tls); proc_terminate (); // clean up process stuff } } @@ -1005,10 +1013,11 @@ wait_sig (VOID *self) debug_printf ("entering ReadFile loop, readsig %p, myself->sendsig %p", readsig, myself->sendsig); + sigpacket pack; for (;;) { DWORD nb; - sigpacket pack; + pack.tls = NULL; if (!ReadFile (readsig, &pack, sizeof (pack), &nb, NULL)) break; @@ -1114,9 +1123,13 @@ wait_sig (VOID *self) break; } - HANDLE h = hMainThread; - my_sendsig = hMainThread = NULL; - DWORD res = !h ? WAIT_OBJECT_0 : WaitForSingleObject (h, INFINITE); + my_sendsig = NULL; + if (!pack.tls) + api_fatal ("no exit packet received"); + if (!pack.tls->thread_handle) + api_fatal ("no thread handle set on exit"); + HANDLE h = pack.tls->thread_handle; + DWORD res = WaitForSingleObject (h, INFINITE); DWORD exitcode = 1; diff --git a/winsup/cygwin/winsup.h b/winsup/cygwin/winsup.h index d31dd9abd..f9004e16d 100644 --- a/winsup/cygwin/winsup.h +++ b/winsup/cygwin/winsup.h @@ -347,6 +347,7 @@ extern HANDLE hMainProc; extern HANDLE hProcToken; extern HANDLE hProcImpToken; extern HANDLE hExeced; +extern CRITICAL_SECTION exit_lock; extern bool cygwin_testing;