Fix for bug 129364. Eliminate a window of time in which notifiers could fire when we hadn't set up the polling thread on the poll descriptors, which could cause lost notifications and FTP stalls. Also revert to PR_FAST_INTSON() from PR_INTSON(), which seems to fix a permanent stall issue on Mac OS X. r=wtc, a=asa NSPRPUB_PRE_4_2_CLIENT_BRANCH
authorsfraser%netscape.com
Sat, 09 Mar 2002 03:00:07 +0000
branchNSPRPUB_PRE_4_2_CLIENT_BRANCH
changeset 2287 74130dd704cb547203adaaf9e120a9468f988e04
parent 2282 588ccb8175dc4d6fb3202db48bfc65e8d1af56bd
child 2292 9d06cd7e79afd11e86a3010317adf80471a64266
push idunknown
push userunknown
push dateunknown
reviewerswtc, asa
bugs129364
Fix for bug 129364. Eliminate a window of time in which notifiers could fire when we hadn't set up the polling thread on the poll descriptors, which could cause lost notifications and FTP stalls. Also revert to PR_FAST_INTSON() from PR_INTSON(), which seems to fix a permanent stall issue on Mac OS X. r=wtc, a=asa
pr/src/md/mac/macsockotpt.c
--- a/pr/src/md/mac/macsockotpt.c
+++ b/pr/src/md/mac/macsockotpt.c
@@ -1929,67 +1929,70 @@ PRInt32 _MD_poll(PRPollDesc *pds, PRIntn
     
     PRInt16     *readFlags  = readFlagsArray;
     PRInt16     *writeFlags = writeFlagsArray;
 
     PRInt16     *ioFlags = NULL;
     
     PRThread    *thread = _PR_MD_CURRENT_THREAD();
     PRInt32     ready;
-    intn        is;
-    PRBool      needsToWait = PR_FALSE;
     
     if (npds > DESCRIPTOR_FLAGS_ARRAY_SIZE)
     {
         // we allocate a single double-size array. The first half is used
         // for read flags, and the second half for write flags.
         ioFlags = (PRInt16*)PR_Malloc(sizeof(PRInt16) * npds * 2);
         if (!ioFlags)
         {
             PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
             return -1;
         }
         
         readFlags = ioFlags;
         writeFlags = &ioFlags[npds];
     }
-    
-    (void)CheckPollDescMethods(pds, npds, readFlags, writeFlags);
 
-    _PR_INTSOFF(is);
-    PR_Lock(thread->md.asyncIOLock);
-    
-    (void)CheckPollDescEndpoints(pds, npds, readFlags, writeFlags);
-    ready = CountReadyPollDescs(pds, npds);
-    
-    if ((ready == 0) && (timeout != PR_INTERVAL_NO_WAIT))
-    {
+    if (timeout != PR_INTERVAL_NO_WAIT) {
+        intn        is;
+        
+        // we have to be outside the lock when calling this, since
+        // it can call arbitrary user code (including other socket
+        // entry points)
+        (void)CheckPollDescMethods(pds, npds, readFlags, writeFlags);
+
+        _PR_INTSOFF(is);
+        PR_Lock(thread->md.asyncIOLock);
         PrepareForAsyncCompletion(thread, 0);
+
         SetDescPollThread(pds, npds, thread);
-        needsToWait = PR_TRUE;
-    }    
-        
-    PR_Unlock(thread->md.asyncIOLock);
-    _PR_INTSON(is);
+
+        (void)CheckPollDescEndpoints(pds, npds, readFlags, writeFlags);
 
-    if (needsToWait)
-    {
-        WaitOnThisThread(thread, timeout);
+        PR_Unlock(thread->md.asyncIOLock);
+        _PR_FAST_INTSON(is);
 
-        // since we may have been woken by a pollable event
-        // firing, we have to check both poll methods and
-        // endpoints.
-        (void)CheckPollDescMethods(pds, npds, readFlags, writeFlags);
-        (void)CheckPollDescEndpoints(pds, npds, readFlags, writeFlags);
         ready = CountReadyPollDescs(pds, npds);
 
+        if (ready == 0) {
+            WaitOnThisThread(thread, timeout);
+
+            // since we may have been woken by a pollable event firing,
+            // we have to check both poll methods and endpoints.
+            (void)CheckPollDescMethods(pds, npds, readFlags, writeFlags);
+            (void)CheckPollDescEndpoints(pds, npds, readFlags, writeFlags);
+            ready = CountReadyPollDescs(pds, npds);
+        }
+        
+        thread->io_pending = PR_FALSE;
         SetDescPollThread(pds, npds, NULL);
     }
     else {
-        thread->io_pending = PR_FALSE;
+        (void)CheckPollDescMethods(pds, npds, readFlags, writeFlags);
+        (void)CheckPollDescEndpoints(pds, npds, readFlags, writeFlags);
+        ready = CountReadyPollDescs(pds, npds);    
     }
 
     if (readFlags != readFlagsArray)
         PR_Free(ioFlags);
     
     return ready;
 }