fix for bug 66508. r=pinkerton, sr=sfraser. Landing fix from 6.0 branch to detect orderlyDisconnects. NSPRPUB_CLIENT_BRANCH
authorgordon%netscape.com
Wed, 07 Feb 2001 01:02:27 +0000
branchNSPRPUB_CLIENT_BRANCH
changeset 1719 27c8cf70995577084e93735f327268fb90e77fd6
parent 1718 84b1e325a6980472f66ef40186e2a1bf5617dde5
child 1722 6868d19d663da0d41360208ece5ead272b85804f
push idunknown
push userunknown
push dateunknown
reviewerspinkerton, sfraser
bugs66508
fix for bug 66508. r=pinkerton, sr=sfraser. Landing fix from 6.0 branch to detect orderlyDisconnects.
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 to handle 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)