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
authorsfraser%netscape.com
Thu, 14 Jun 2001 01:35:05 +0000
changeset 1940 d74fafff1a276314246838a35b5f15466a66b8aa
parent 1936 ccaea6e28532f5535299bee5751b0729cf1ac44b
child 1941 9766815decf67a388bbc7d61ef3b300911b2c79b
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
@@ -1403,17 +1403,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
@@ -1422,24 +1424,29 @@ 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
+					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			
@@ -1451,40 +1458,49 @@ 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
+					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) {