* 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.
This commit is contained in:
parent
329b9ead3e
commit
d525130f04
@ -1,3 +1,24 @@
|
||||
2002-10-22 Christopher Faylor <cgf@redhat.com>
|
||||
|
||||
* 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 <pierre.humblet@ieee.org>
|
||||
|
||||
* sec_helper.cc (cygsid::get_id): If the sid matches a sid stored in
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);}
|
||||
|
@ -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. */
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user