Fix for bug 85514 -- use OTEnter/LeaveNotifer calls to fix synchronization problem caused by the OT notifier firing while we are inside OTSnd or OTRcv. r=gordon, wtc. a=blizzard NSPRPUB_CLIENT_BRANCH
authorsfraser%netscape.com
Thu, 14 Jun 2001 01:33:06 +0000
branchNSPRPUB_CLIENT_BRANCH
changeset 1938 4071778627e03c53f971ab255e4318fb865c1dba
parent 1929 98c89678893b36461b2c9266640a6bfcb3cdb95d
child 1939 913aa4206148b2b06b48bf62f803b1a418463217
child 1959 654d42b6739f119d325ef15a48d00323a18068ce
push idunknown
push userunknown
push dateunknown
reviewersgordon, wtc, blizzard
bugs85514
Fix for bug 85514 -- use OTEnter/LeaveNotifer calls to fix synchronization problem caused by the OT notifier firing while we are inside OTSnd or OTRcv. r=gordon, wtc. a=blizzard
pr/src/md/mac/macsockotpt.c
--- a/pr/src/md/mac/macsockotpt.c
+++ b/pr/src/md/mac/macsockotpt.c
@@ -1386,17 +1386,19 @@ static PRInt32 SendReceiveStream(PRFileD
         goto ErrorExit;
     }
         
     if (buf == NULL) {
         err = kEFAULTErr;
         goto ErrorExit;
     }
     
-    while (bytesLeft > 0) {
+    while (bytesLeft > 0)
+    {
+        Boolean disabledNotifications = OTEnterNotifier(endpoint);
     
         PrepareForAsyncCompletion(me, fd->secret->md.osfd);    
 
         if (opCode == kSTREAM_SEND) {
         	do {
 
 				fd->secret->md.write.thread = me;
 				fd->secret->md.writeReady = PR_FALSE;				// expect the worst
@@ -1405,25 +1407,30 @@ static PRInt32 SendReceiveStream(PRFileD
 				if (fd->secret->nonblocking)							// hope for the best
 					break;
 				else {
 
 					// We drop through on anything other than a blocking write.
 					if (result != kOTFlowErr)
 						break;
 
-					// Blocking write, but the pipe is full. Wait for an event,
-					// hoping that it's a T_GODATA event.
+					// Blocking write, but the pipe is full. Turn notifications on and
+					// wait for an event, hoping that it's a T_GODATA event.
+                    if (disabledNotifications) {
+                        OTLeaveNotifier(endpoint);
+                        disabledNotifications = false;
+                    }
 					WaitOnThisThread(me, PR_INTERVAL_NO_TIMEOUT);
 					result = me->md.osErrCode;
 					if (result != kOTNoError) // got interrupted, or some other error
 						break;
 
 					// Prepare to loop back and try again
-  			   		PrepareForAsyncCompletion(me, fd->secret->md.osfd);  
+					disabledNotifications = OTEnterNotifier(endpoint);
+  			   		PrepareForAsyncCompletion(me, fd->secret->md.osfd);
 				}
 			}
 			while(1);
         } else {
         	do {
 				fd->secret->md.read.thread = me;
 				fd->secret->md.readReady = PR_FALSE;				// expect the worst			
 	            result = OTRcv(endpoint, buf, bytesLeft, NULL);
@@ -1434,41 +1441,50 @@ static PRInt32 SendReceiveStream(PRFileD
 					if (result != kOTNoDataErr) {
 			      		// If we successfully read a blocking socket, check for more data.
 			      		// According to IM:OT, we should be able to rely on OTCountDataBytes
 			      		// to tell us whether there is a nonzero amount of data pending.
 			        	size_t count;
 			        	OSErr tmpResult;
 			        	tmpResult = OTCountDataBytes(endpoint, &count);
 				        fd->secret->md.readReady = ((tmpResult == kOTNoError) && (count > 0));
-		
 						break;
 				    }
 
-					// Blocking read, but no data available. Wait for an event
-					// on this endpoint, and hope that we get a T_DATA event.
+					// Blocking read, but no data available. Turn notifications on and
+					// wait for an event on this endpoint, and hope that we get a T_DATA event.
+                    if (disabledNotifications) {
+                        OTLeaveNotifier(endpoint);
+                        disabledNotifications = false;
+                    }
 					WaitOnThisThread(me, PR_INTERVAL_NO_TIMEOUT);
 					result = me->md.osErrCode;
 					if (result != kOTNoError) // interrupted thread, etc.
 						break;
 
 					// Prepare to loop back and try again
-  			   		PrepareForAsyncCompletion(me, fd->secret->md.osfd);  
+					disabledNotifications = OTEnterNotifier(endpoint);
+  			   		PrepareForAsyncCompletion(me, fd->secret->md.osfd);
 				}
 			}
 			// Retry read if we had to wait for data to show up.
 			while(1);
         }
 
 		me->io_pending = PR_FALSE;
+		
         if (opCode == kSTREAM_SEND)
-            fd->secret->md.write.thread = nil;
+            fd->secret->md.write.thread = NULL;
         else
-            fd->secret->md.read.thread  = nil;
+            fd->secret->md.read.thread  = NULL;
 
+        // turn notifications back on
+        if (disabledNotifications)
+            OTLeaveNotifier(endpoint);
+            
         if (result > 0) {
             buf = (void *) ( (UInt32) buf + (UInt32)result );
             bytesLeft -= result;
             if (opCode == kSTREAM_RECEIVE)
                 return result;
         } else {
 			switch (result) {
 				case kOTLookErr: