summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorwtc%netscape.com <devnull@localhost>2002-08-28 00:04:47 +0000
committerwtc%netscape.com <devnull@localhost>2002-08-28 00:04:47 +0000
commit502fab4f1aaf766ed733153da125a1b6d83d3717 (patch)
tree3c553a8c41c6f0f13ec9773a7d218d3a8b46fc80
parent7bd0baf13441d9b70df98b0adaed59def1777020 (diff)
downloadnspr-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.h2
-rw-r--r--pr/include/private/primpl.h9
-rw-r--r--pr/src/md/windows/ntthread.c15
-rw-r--r--pr/src/misc/prinit.c3
-rw-r--r--pr/src/threads/combined/prucpu.c31
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