diff options
author | wtc%netscape.com <devnull@localhost> | 2002-08-28 00:04:47 +0000 |
---|---|---|
committer | wtc%netscape.com <devnull@localhost> | 2002-08-28 00:04:47 +0000 |
commit | 502fab4f1aaf766ed733153da125a1b6d83d3717 (patch) | |
tree | 3c553a8c41c6f0f13ec9773a7d218d3a8b46fc80 | |
parent | 7bd0baf13441d9b70df98b0adaed59def1777020 (diff) | |
download | nspr-hg-502fab4f1aaf766ed733153da125a1b6d83d3717.tar.gz |
Bug 161998: fixed the race condition between PR_Cleanup and a CPU thread
that times out from the GetQueuedCompletionStatus call in the WINNT build.
The fix is to shut down the CPU threads in PR_Cleanup.
Modified Files: _winnt.h primpl.h ntthread.c prinit.c prucpu.c
-rw-r--r-- | pr/include/md/_winnt.h | 2 | ||||
-rw-r--r-- | pr/include/private/primpl.h | 9 | ||||
-rw-r--r-- | pr/src/md/windows/ntthread.c | 15 | ||||
-rw-r--r-- | pr/src/misc/prinit.c | 3 | ||||
-rw-r--r-- | pr/src/threads/combined/prucpu.c | 31 |
5 files changed, 60 insertions, 0 deletions
diff --git a/pr/include/md/_winnt.h b/pr/include/md/_winnt.h index de8a2cf7..8a5b7041 100644 --- a/pr/include/md/_winnt.h +++ b/pr/include/md/_winnt.h @@ -346,6 +346,8 @@ extern int _PR_NTFiberSafeSelect(int, fd_set *, fd_set *, fd_set *, #define _MD_INIT_THREAD _PR_MD_INIT_THREAD #define _MD_INIT_ATTACHED_THREAD _PR_MD_INIT_THREAD #define _MD_CREATE_THREAD _PR_MD_CREATE_THREAD +#define _MD_JOIN_THREAD _PR_MD_JOIN_THREAD +#define _MD_END_THREAD _PR_MD_END_THREAD #define _MD_YIELD _PR_MD_YIELD #define _MD_SET_PRIORITY _PR_MD_SET_PRIORITY #define _MD_CLEAN_THREAD _PR_MD_CLEAN_THREAD diff --git a/pr/include/private/primpl.h b/pr/include/private/primpl.h index f6a1f63d..5455ed9c 100644 --- a/pr/include/private/primpl.h +++ b/pr/include/private/primpl.h @@ -1022,6 +1022,12 @@ extern PRStatus _PR_MD_CREATE_THREAD( PRUint32 stackSize); #define _PR_MD_CREATE_THREAD _MD_CREATE_THREAD +extern void _PR_MD_JOIN_THREAD(_MDThread *md); +#define _PR_MD_JOIN_THREAD _MD_JOIN_THREAD + +extern void _PR_MD_END_THREAD(void); +#define _PR_MD_END_THREAD _MD_END_THREAD + extern void _PR_MD_YIELD(void); #define _PR_MD_YIELD _MD_YIELD @@ -1757,6 +1763,9 @@ extern void _PR_CleanupIO(void); extern void _PR_CleanupNet(void); extern void _PR_CleanupLayerCache(void); extern void _PR_CleanupStacks(void); +#ifdef WINNT +extern void _PR_CleanupCPUs(void); +#endif extern void _PR_CleanupThreads(void); extern void _PR_CleanupTPD(void); extern void _PR_Cleanup(void); diff --git a/pr/src/md/windows/ntthread.c b/pr/src/md/windows/ntthread.c index 1c3fb531..a414e5c7 100644 --- a/pr/src/md/windows/ntthread.c +++ b/pr/src/md/windows/ntthread.c @@ -254,6 +254,21 @@ _PR_MD_CREATE_THREAD(PRThread *thread, return PR_FAILURE; } +void +_PR_MD_JOIN_THREAD(_MDThread *md) +{ + DWORD rv; + + rv = WaitForSingleObject(md->handle, INFINITE); + PR_ASSERT(WAIT_OBJECT_0 == rv); +} + +void +_PR_MD_END_THREAD(void) +{ + _endthreadex(0); +} + void _PR_MD_YIELD(void) { diff --git a/pr/src/misc/prinit.c b/pr/src/misc/prinit.c index 944ff5d5..cd55a9fb 100644 --- a/pr/src/misc/prinit.c +++ b/pr/src/misc/prinit.c @@ -451,6 +451,9 @@ PR_IMPLEMENT(PRStatus) PR_Cleanup() */ _PR_CleanupNet(); _PR_CleanupIO(); +#ifdef WINNT + _PR_CleanupCPUs(); +#endif _PR_CleanupThreads(); PR_DestroyLock(_pr_sleeplock); _pr_sleeplock = NULL; diff --git a/pr/src/threads/combined/prucpu.c b/pr/src/threads/combined/prucpu.c index be4203d6..3d575d6c 100644 --- a/pr/src/threads/combined/prucpu.c +++ b/pr/src/threads/combined/prucpu.c @@ -117,6 +117,31 @@ void _PR_InitCPUs() _PR_MD_INIT_CPUS(); } +#ifdef WINNT +/* + * Right now this function merely stops the CPUs and does + * not do any other cleanup. + * + * It is only implemented for WINNT because bug 161998 only + * affects the WINNT version of NSPR, but it would be nice + * to implement this function for other platforms too. + */ +void _PR_CleanupCPUs(void) +{ + PRUintn i; + PRCList *qp; + _PRCPU *cpu; + + _pr_cpus_exit = 1; + for (i = 0; i < _pr_numCPU; i++) { + _PR_MD_WAKEUP_WAITER(NULL); + } + for (qp = _PR_CPUQ().next; qp != &_PR_CPUQ(); qp = qp->next) { + cpu = _PR_CPU_PTR(qp); + _PR_MD_JOIN_THREAD(&cpu->thread->md); + } +} +#endif static _PRCPUQueue *_PR_CreateCPUQueue(void) { @@ -332,6 +357,12 @@ static void PR_CALLBACK _PR_CPU_Idle(void *_cpu) /* Wait for an IO to complete */ (void)_PR_MD_PAUSE_CPU(timeout); +#ifdef WINNT + if (_pr_cpus_exit) { + /* _PR_CleanupCPUs tells us to exit */ + _PR_MD_END_THREAD(); + } +#endif #if !defined(_PR_LOCAL_THREADS_ONLY) && !defined(_PR_GLOBAL_THREADS_ONLY) #ifdef _PR_HAVE_ATOMIC_OPS |