Fix for Bugscape 3003. Modified SendReceiveStream to differentiate OrderlyDisconnects from Endpoint destruction due to sleep or tcp setting changes. Netscape_20000922_BRANCH
authorgordon%netscape.com
Wed, 01 Nov 2000 22:45:55 +0000
branchNetscape_20000922_BRANCH
changeset 1613 1c2bf754e11135f821cd1d7d9a4a2570c514faca
parent 1597 7403d34074273b83947e7f26b4179ff4c55fc100
push idunknown
push userunknown
push dateunknown
Fix for Bugscape 3003. Modified SendReceiveStream to differentiate OrderlyDisconnects from Endpoint destruction due to sleep or tcp setting changes. r=sdagley, wtc, sr=sfraser.
pr/include/md/_macos.h
pr/src/md/mac/macsockotpt.c
--- a/pr/include/md/_macos.h
+++ b/pr/include/md/_macos.h
@@ -86,17 +86,17 @@ struct _MDCPU {
 
 typedef struct _MDSocketCallerInfo {
 	PRThread *	thread;
 	void *		cookie;
 } _MDSocketCallerInfo;
 
 struct _MDFileDesc {
     PRInt32     osfd;
-	PRBool      connectionOpen;
+	PRBool      orderlyDisconnect;
 	PRBool      readReady;
 	PRBool      writeReady;
 	PRBool      exceptReady;
 	PRLock *    miscLock;
 	
 	/* Server sockets: listen bit tells the notifier func what to do */
 	PRBool		doListen;
 	
--- a/pr/src/md/mac/macsockotpt.c
+++ b/pr/src/md/mac/macsockotpt.c
@@ -320,17 +320,16 @@ static pascal void  NotifierRoutine(void
 			// cookie = sndCall parameter from OTConnect()
             err = OTRcvConnect(endpoint, NULL);
             PR_ASSERT(err == kOTNoError);
 
 			// wake up waiting thread, if any
             thread = secret->md.write.thread;
             secret->md.write.thread    = NULL;
             secret->md.write.cookie    = cookie;
-            secret->md.connectionOpen  = PR_TRUE;
             break;
 
         case T_DATA:        // Standard data is available
 			// Mark this socket as readable.
 			secret->md.readReady = PR_TRUE;
 
 			// wake up waiting thread, if any
             thread = secret->md.read.thread;
@@ -342,17 +341,16 @@ static pascal void  NotifierRoutine(void
             PR_ASSERT(!"T_EXDATA Not implemented");
 			return;
 
         case T_DISCONNECT:  // A disconnect is available
             discon.udata.len = 0;
             err = OTRcvDisconnect(endpoint, &discon);
             PR_ASSERT(err == kOTNoError);
             secret->md.exceptReady     = PR_TRUE;
-            secret->md.connectionOpen  = PR_FALSE;
 
 			// wake up waiting threads, if any
 			result = -3199 - discon.reason; // obtain the negative error code
 
             if ((thread = secret->md.read.thread) != NULL) {
 		        secret->md.read.thread    = NULL;
     	        secret->md.read.cookie    = cookie;
             	WakeUpNotifiedThread(thread, result);
@@ -375,17 +373,17 @@ static pascal void  NotifierRoutine(void
 			(void) OTRcvUDErr((EndpointRef) cookie, NULL);
             break;
 
         case T_ORDREL:      // An orderly release is available
             err = OTRcvOrderlyDisconnect(endpoint);
             PR_ASSERT(err == kOTNoError);
             secret->md.readReady      = PR_TRUE;   // mark readable (to emulate bsd sockets)
             // remember connection is closed, so we can return 0 on read or receive
-			secret->md.connectionOpen = PR_FALSE;
+			secret->md.orderlyDisconnect = PR_TRUE;
 	
             thread = secret->md.read.thread;
 	        secret->md.read.thread    = NULL;
 	        secret->md.read.cookie    = cookie;
 
             break;		
 
         case T_GODATA:   // Flow control lifted on standard data
@@ -1479,17 +1477,19 @@ static PRInt32 SendReceiveStream(PRFileD
 					}
 
 					WaitOnThisThread(me, timeout);
 					err = me->md.osErrCode;
 					if (err != kOTNoError)
 						goto ErrorExit;				
 					break;
 					
-				case kOTOutStateErr:	// it has been closed, fall through for error
+				case kOTOutStateErr:	// if provider already closed, fall through to handle error
+					if (fd->secret->md.orderlyDisconnect)
+						return 0;
 				default:
 					err = result;
 					goto ErrorExit;
 			}
 		}
     }
 
     PR_ASSERT(opCode == kSTREAM_SEND ? fd->secret->md.write.thread == nil :
@@ -1772,17 +1772,17 @@ void _MD_initfiledesc(PRFileDesc *fd)
 	// We presume that only one thread will be making Read calls (Recv/Accept) and that only
 	// one thread will be making Write calls (Send/Connect) on the endpoint at a time.
 	if (fd->methods->file_type == PR_DESC_SOCKET_TCP ||
 		fd->methods->file_type == PR_DESC_SOCKET_UDP )
 	{
 		PR_ASSERT(fd->secret->md.miscLock == NULL);
 		fd->secret->md.miscLock = PR_NewLock();
 		PR_ASSERT(fd->secret->md.miscLock != NULL);
-		fd->secret->md.connectionOpen = PR_FALSE;	// starts out closed
+		fd->secret->md.orderlyDisconnect = PR_FALSE;
 		fd->secret->md.readReady = PR_FALSE;		// let's not presume we have data ready to read
 		fd->secret->md.writeReady = PR_TRUE;		// let's presume we can write unless we hear otherwise
 		fd->secret->md.exceptReady = PR_FALSE;
 	}
 }
 
 
 void _MD_freefiledesc(PRFileDesc *fd)