diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index ae748e04c..dd05d4a8b 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,24 @@ +2002-10-22 Christopher Faylor + + * cygthread.cc (cygthread::exiting): New variable. + (cygthread::initialized): Delete. + (cygthread::stub): Use exiting variable to determine when to exit. + (cygthread::runner): Delete. + (cygthread_protect): New variable. + (cygthread::init): Don't start runner thread. Initialize muto for list + protection. + (cygthread::freerange): Return pointer to cygthread. + (cygthread::operator new): Change logic to start threads on an + as-needed basis. + (cygthread::detach): Don't zero id. + (cygthread::terminate): Don't kill any executing threads. Just set + exiting flag. + * cygthread.h (cygthread): Reflect above changes. + * dcrt0.cc (dll_crt0_1): Move cygthread initialization later. + + * fork.cc (fork_child): Do fdtab fixup after dll fixup or (apparently) + winsock may allocate memory in dll load address. + 2002-10-22 Pierre Humblet * sec_helper.cc (cygsid::get_id): If the sid matches a sid stored in diff --git a/winsup/cygwin/cygthread.cc b/winsup/cygwin/cygthread.cc index 7143d70bb..70225f0cf 100644 --- a/winsup/cygwin/cygthread.cc +++ b/winsup/cygwin/cygthread.cc @@ -12,6 +12,7 @@ details. */ #include "exceptions.h" #include "security.h" #include "cygthread.h" +#include "sync.h" #undef CloseHandle @@ -19,7 +20,7 @@ static cygthread NO_COPY threads[9]; #define NTHREADS (sizeof (threads) / sizeof (threads[0])) DWORD NO_COPY cygthread::main_thread_id; -int NO_COPY cygthread::initialized; +bool NO_COPY cygthread::exiting; /* Initial stub called by cygthread constructor. Performs initial per-thread initialization and loops waiting for new thread functions @@ -48,7 +49,7 @@ cygthread::stub (VOID *arg) system_printf ("erroneous thread activation"); else { - if (!info->func || initialized < 0) + if (!info->func || exiting) ExitThread (0); /* Cygwin threads should not call ExitThread directly */ @@ -89,33 +90,12 @@ cygthread::simplestub (VOID *arg) ExitThread (0); } -/* This function runs in a secondary thread and starts up a bunch of - other suspended threads for use in the cygthread pool. */ -DWORD WINAPI -cygthread::runner (VOID *arg) -{ - for (unsigned i = 0; i < NTHREADS; i++) - if (!initialized) - threads[i].h = CreateThread (&sec_none_nih, 0, cygthread::stub, - &threads[i], CREATE_SUSPENDED, - &threads[i].avail); - else - ExitThread (0); - - initialized ^= 1; - ExitThread (0); -} - -HANDLE NO_COPY runner_handle; -DWORD NO_COPY runner_tid; +static NO_COPY muto *cygthread_protect; /* Start things going. Called from dll_crt0_1. */ void cygthread::init () { - runner_handle = CreateThread (&sec_none_nih, 0, cygthread::runner, NULL, 0, - &runner_tid); - if (!runner_handle) - api_fatal ("can't start thread_runner, %E"); + new_muto (cygthread_protect); main_thread_id = GetCurrentThreadId (); } @@ -131,7 +111,7 @@ cygthread::is () return 0; } -void * +cygthread * cygthread::freerange () { cygthread *self = (cygthread *) calloc (1, sizeof (*self)); @@ -148,39 +128,36 @@ new (size_t) DWORD id; cygthread *info; - for (;;) - { - int was_initialized = initialized; - if (was_initialized < 0) - ExitThread (0); + cygthread_protect->acquire (); - /* Search the threads array for an empty slot to use */ - for (info = threads + NTHREADS - 1; info >= threads; info--) - if ((id = (DWORD) InterlockedExchange ((LPLONG) &info->avail, 0))) - { - info->id = id; + /* Search the threads array for an empty slot to use */ + for (info = threads; info < threads + NTHREADS; info++) + if ((id = (DWORD) InterlockedExchange ((LPLONG) &info->avail, 0))) + { #ifdef DEBUGGING - if (info->__name) - api_fatal ("name not NULL? id %p, i %d", id, info - threads); + if (info->__name) + api_fatal ("name not NULL? id %p, i %d", id, info - threads); #endif - return info; - } + goto out; + } + else if (!info->id) + { + info->h = CreateThread (&sec_none_nih, 0, cygthread::stub, info, + CREATE_SUSPENDED, &info->id); + goto out; + } - if (was_initialized < 0) - ExitThread (0); - - if (!was_initialized) - Sleep (0); /* thread_runner is not finished yet. */ - else - { #ifdef DEBUGGING - char buf[1024]; - if (!GetEnvironmentVariable ("CYGWIN_NOFREERANGE_NOCHECK", buf, sizeof (buf))) - api_fatal ("Overflowed cygwin thread pool"); + char buf[1024]; + if (!GetEnvironmentVariable ("CYGWIN_NOFREERANGE_NOCHECK", buf, sizeof (buf))) + api_fatal ("Overflowed cygwin thread pool"); #endif - return freerange (); - } - } + + info = freerange (); /* exhausted thread pool */ + +out: + cygthread_protect->release (); + return info; } cygthread::cygthread (LPTHREAD_START_ROUTINE start, LPVOID param, @@ -200,9 +177,7 @@ cygthread::cygthread (LPTHREAD_START_ROUTINE start, LPVOID param, Sleep (0); } #endif - __name = name; /* Need to set after thread has woken up to - ensure that it won't be cleared by exiting - thread. */ + __name = name; if (!thread_sync) ResumeThread (h); else @@ -278,7 +253,6 @@ cygthread::detach () } else { - id = 0; ResetEvent (*this); /* Mark the thread as available by setting avail to non-zero */ (void) InterlockedExchange ((LPLONG) &this->avail, avail); @@ -289,37 +263,5 @@ cygthread::detach () void cygthread::terminate () { - /* Wow. All of this seems to be necessary or (on Windows 9x at least) the - process will sometimes deadlock if there are suspended threads. I assume - that something funky is happening like a suspended thread being created - while the process is exiting or something. In particular, it seems like - the WaitForSingleObjects are necessary since it appears that the - TerminateThread call may happen asynchronously, i.e., when TerminateThread - returns, the thread may not yet have terminated. */ - if (runner_handle && initialized >= 0) - { - /* Don't care about detaching (or attaching) threads now */ - if (cygwin_hmodule && !DisableThreadLibraryCalls (cygwin_hmodule)) - system_printf ("DisableThreadLibraryCalls (%p) failed, %E", - cygwin_hmodule); - initialized = -1; - (void) TerminateThread (runner_handle, 0); - (void) WaitForSingleObject (runner_handle, INFINITE); - (void) CloseHandle (runner_handle); - HANDLE hthreads[NTHREADS]; - int n = 0; - for (unsigned i = 0; i < NTHREADS; i++) - if (threads[i].h) - { - hthreads[n] = threads[i].h; - threads[i].h = NULL; - TerminateThread (hthreads[n++], 0); - } - if (n) - { - (void) WaitForMultipleObjects (n, hthreads, TRUE, INFINITE); - while (--n >= 0) - CloseHandle (hthreads[n]); - } - } + exiting = 1; } diff --git a/winsup/cygwin/cygthread.h b/winsup/cygwin/cygthread.h index ded205f30..774c656da 100644 --- a/winsup/cygwin/cygthread.h +++ b/winsup/cygwin/cygthread.h @@ -18,9 +18,7 @@ class cygthread VOID *arg; bool is_freerange; static DWORD main_thread_id; - static int initialized; - static DWORD WINAPI runner (VOID *); - static DWORD WINAPI free_runner (VOID *); + static bool exiting; static DWORD WINAPI stub (VOID *); static DWORD WINAPI simplestub (VOID *); public: @@ -32,7 +30,7 @@ class cygthread operator HANDLE (); static bool is (); void * operator new (size_t); - static void * freerange (); + static cygthread *freerange (); void exit_thread (); static void terminate (); bool SetThreadPriority (int nPriority) {return ::SetThreadPriority (h, nPriority);} diff --git a/winsup/cygwin/dcrt0.cc b/winsup/cygwin/dcrt0.cc index 89c9a4456..22899e452 100644 --- a/winsup/cygwin/dcrt0.cc +++ b/winsup/cygwin/dcrt0.cc @@ -573,10 +573,7 @@ dll_crt0_1 () char **envp = NULL; if (!child_proc_info) - { - cygthread::init (); - memory_init (); - } + memory_init (); else { bool close_ppid_handle = false; @@ -587,7 +584,6 @@ dll_crt0_1 () alloc_stack (fork_info); cygheap_fixup_in_child (0); memory_init (); - cygthread::init (); set_myself (mypid); close_ppid_handle = !!child_proc_info->pppid_handle; break; @@ -600,7 +596,6 @@ dll_crt0_1 () hexec_proc = spawn_info->hexec_proc; around: HANDLE h; - cygthread::init (); cygheap_fixup_in_child (1); memory_init (); if (!spawn_info->moreinfo->myself_pinfo || @@ -621,7 +616,6 @@ dll_crt0_1 () old_title = strcpy (title_buf, spawn_info->moreinfo->old_title); cfree (spawn_info->moreinfo->old_title); } - // cygthread::init (); break; } if (close_hexec_proc) @@ -632,6 +626,7 @@ dll_crt0_1 () ProtectHandle (hMainProc); ProtectHandle (hMainThread); + cygthread::init (); /* Initialize debug muto, if DLL is built with --enable-debugging. Need to do this before any helper threads start. */ diff --git a/winsup/cygwin/fork.cc b/winsup/cygwin/fork.cc index 165c794ca..a547c7721 100644 --- a/winsup/cygwin/fork.cc +++ b/winsup/cygwin/fork.cc @@ -281,8 +281,6 @@ fork_child (HANDLE& hParent, dll *&first_dll, bool& load_dlls) if (fixup_mmaps_after_fork (hParent)) api_fatal ("recreate_mmaps_after_fork_failed"); - cygheap->fdtab.fixup_after_fork (hParent); - ProtectHandleINH (hParent); MALLOC_CHECK; @@ -291,10 +289,16 @@ fork_child (HANDLE& hParent, dll *&first_dll, bool& load_dlls) that we're done, and wait for the parent to fill in the. loaded dlls' data/bss. */ if (!load_dlls) - sync_with_parent ("performed fork fixup.", FALSE); + { + cygheap->fdtab.fixup_after_fork (hParent); + ProtectHandleINH (hParent); + sync_with_parent ("performed fork fixup.", FALSE); + } else { dlls.load_after_fork (hParent, first_dll); + cygheap->fdtab.fixup_after_fork (hParent); + ProtectHandleINH (hParent); sync_with_parent ("loaded dlls", TRUE); }