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

This commit is contained in:
sfraser%netscape.com 2001-06-14 01:35:05 +00:00
Родитель 8363ca6e21
Коммит 8f7cf3781e
1 изменённых файлов: 24 добавлений и 8 удалений

Просмотреть файл

@ -1408,7 +1408,9 @@ static PRInt32 SendReceiveStream(PRFileDesc *fd, void *buf, PRInt32 amount,
goto ErrorExit; goto ErrorExit;
} }
while (bytesLeft > 0) { while (bytesLeft > 0)
{
Boolean disabledNotifications = OTEnterNotifier(endpoint);
PrepareForAsyncCompletion(me, fd->secret->md.osfd); PrepareForAsyncCompletion(me, fd->secret->md.osfd);
@ -1427,14 +1429,19 @@ static PRInt32 SendReceiveStream(PRFileDesc *fd, void *buf, PRInt32 amount,
if (result != kOTFlowErr) if (result != kOTFlowErr)
break; break;
// Blocking write, but the pipe is full. Wait for an event, // Blocking write, but the pipe is full. Turn notifications on and
// hoping that it's a T_GODATA event. // wait for an event, hoping that it's a T_GODATA event.
if (disabledNotifications) {
OTLeaveNotifier(endpoint);
disabledNotifications = false;
}
WaitOnThisThread(me, PR_INTERVAL_NO_TIMEOUT); WaitOnThisThread(me, PR_INTERVAL_NO_TIMEOUT);
result = me->md.osErrCode; result = me->md.osErrCode;
if (result != kOTNoError) // got interrupted, or some other error if (result != kOTNoError) // got interrupted, or some other error
break; break;
// Prepare to loop back and try again // Prepare to loop back and try again
disabledNotifications = OTEnterNotifier(endpoint);
PrepareForAsyncCompletion(me, fd->secret->md.osfd); PrepareForAsyncCompletion(me, fd->secret->md.osfd);
} }
} }
@ -1456,18 +1463,22 @@ static PRInt32 SendReceiveStream(PRFileDesc *fd, void *buf, PRInt32 amount,
OSErr tmpResult; OSErr tmpResult;
tmpResult = OTCountDataBytes(endpoint, &count); tmpResult = OTCountDataBytes(endpoint, &count);
fd->secret->md.readReady = ((tmpResult == kOTNoError) && (count > 0)); fd->secret->md.readReady = ((tmpResult == kOTNoError) && (count > 0));
break; break;
} }
// Blocking read, but no data available. Wait for an event // Blocking read, but no data available. Turn notifications on and
// on this endpoint, and hope that we get a T_DATA event. // 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); WaitOnThisThread(me, PR_INTERVAL_NO_TIMEOUT);
result = me->md.osErrCode; result = me->md.osErrCode;
if (result != kOTNoError) // interrupted thread, etc. if (result != kOTNoError) // interrupted thread, etc.
break; break;
// Prepare to loop back and try again // Prepare to loop back and try again
disabledNotifications = OTEnterNotifier(endpoint);
PrepareForAsyncCompletion(me, fd->secret->md.osfd); PrepareForAsyncCompletion(me, fd->secret->md.osfd);
} }
} }
@ -1476,10 +1487,15 @@ static PRInt32 SendReceiveStream(PRFileDesc *fd, void *buf, PRInt32 amount,
} }
me->io_pending = PR_FALSE; me->io_pending = PR_FALSE;
if (opCode == kSTREAM_SEND) if (opCode == kSTREAM_SEND)
fd->secret->md.write.thread = nil; fd->secret->md.write.thread = NULL;
else else
fd->secret->md.read.thread = nil; fd->secret->md.read.thread = NULL;
// turn notifications back on
if (disabledNotifications)
OTLeaveNotifier(endpoint);
if (result > 0) { if (result > 0) {
buf = (void *) ( (UInt32) buf + (UInt32)result ); buf = (void *) ( (UInt32) buf + (UInt32)result );