Fix for bug 97866. Fixes async file I/O to ensure that we always call WaitOnThisThread if we're doing an async call (which does not wait if the notifier has already fired). Also don't bother checking return values from PBRead/WriteAsync, since they never fail, but do check the return value of the PBReadSync call. Fixes synchronization problems on Mac OS X. r=gordon, a=wtc.

This commit is contained in:
sfraser%netscape.com 2001-09-20 00:07:43 +00:00
Родитель 1856815ff1
Коммит 1498bf8a26
1 изменённых файлов: 26 добавлений и 29 удалений

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

@ -231,9 +231,9 @@ PRInt32 ReadWriteProc(PRFileDesc *fd, void *buf, PRUint32 bytes, IOOperation op)
{ {
PRInt32 refNum = fd->secret->md.osfd; PRInt32 refNum = fd->secret->md.osfd;
OSErr err; OSErr err;
ExtendedParamBlock pbAsync; ExtendedParamBlock pbAsync;
PRThread *me = _PR_MD_CURRENT_THREAD(); PRThread *me = _PR_MD_CURRENT_THREAD();
_PRCPU *cpu = _PR_MD_CURRENT_CPU(); _PRCPU *cpu = _PR_MD_CURRENT_CPU();
/* quick hack to allow PR_fprintf, etc to work with stderr, stdin, stdout */ /* quick hack to allow PR_fprintf, etc to work with stderr, stdin, stdout */
/* note, if a user chooses "seek" or the like as an operation in another function */ /* note, if a user chooses "seek" or the like as an operation in another function */
@ -254,12 +254,13 @@ PRInt32 ReadWriteProc(PRFileDesc *fd, void *buf, PRUint32 bytes, IOOperation op)
} }
return (bytes); return (bytes);
} }
else else
{ {
static IOCompletionUPP sCompletionUPP = NULL; static IOCompletionUPP sCompletionUPP = NULL;
PRBool doingAsync = PR_FALSE;
/* allocate the callback Universal Procedure Pointer (UPP). This actually allocates /* allocate the callback Universal Procedure Pointer (UPP). This actually allocates
a 32 byte Ptr in the heap, so only do this once a 32 byte Ptr in the heap, so only do this once
*/ */
@ -280,9 +281,11 @@ PRInt32 ReadWriteProc(PRFileDesc *fd, void *buf, PRUint32 bytes, IOOperation op)
/* /*
** Issue the async read call and wait for the io semaphore associated ** Issue the async read call and wait for the io semaphore associated
** with this thread. ** with this thread.
** Don't compute error code from async call. Bug in OS returns a garbage value. ** Async file system calls *never* return error values, so ignore their
** results (see <http://developer.apple.com/technotes/fl/fl_515.html>);
** the completion routine is always called.
*/ */
me->io_fd = refNum; me->io_fd = refNum;
me->md.osErrCode = noErr; me->md.osErrCode = noErr;
if (op == READ_ASYNC) if (op == READ_ASYNC)
{ {
@ -292,39 +295,33 @@ PRInt32 ReadWriteProc(PRFileDesc *fd, void *buf, PRUint32 bytes, IOOperation op)
*/ */
if ( bytes > 20480L ) if ( bytes > 20480L )
{ {
err = PBReadAsync(&pbAsync.pb); doingAsync = PR_TRUE;
if (err != noErr && err != eofErr) me->io_pending = PR_TRUE;
goto ErrorExit;
me->io_pending = PR_TRUE; /* Only mark thread io pending if async call worked */ (void)PBReadAsync(&pbAsync.pb);
} }
else else
{ {
(void) PBReadSync(&pbAsync.pb); pbAsync.pb.ioParam.ioCompletion = NULL;
/* me->io_pending = PR_FALSE;
** This is probbaly redundant but want to make sure we indicate the read
** is complete so we don't wander off into the Sargasso Sea of Mac err = PBReadSync(&pbAsync.pb);
** threading if (err != noErr && err != eofErr)
*/ goto ErrorExit;
pbAsync.pb.ioParam.ioResult = 0;
} }
} }
else else
{ {
doingAsync = PR_TRUE;
me->io_pending = PR_TRUE;
/* writes are currently always async */ /* writes are currently always async */
err = PBWriteAsync(&pbAsync.pb); (void)PBWriteAsync(&pbAsync.pb);
if (err != noErr)
goto ErrorExit;
/* Didn't get an error on the asyn call so mark thread io pending */
me->io_pending = PR_TRUE;
} }
/* See if the i/o call is still pending before we actually yield */ if (doingAsync) {
if (pbAsync.pb.ioParam.ioResult == 1)
WaitOnThisThread(me, PR_INTERVAL_NO_TIMEOUT); WaitOnThisThread(me, PR_INTERVAL_NO_TIMEOUT);
else }
me->io_pending = PR_FALSE; /* io completed so don't mark thread io pending */
} }
err = me->md.osErrCode; err = me->md.osErrCode;
@ -334,13 +331,13 @@ PRInt32 ReadWriteProc(PRFileDesc *fd, void *buf, PRUint32 bytes, IOOperation op)
err = pbAsync.pb.ioParam.ioResult; err = pbAsync.pb.ioParam.ioResult;
if (err != noErr && err != eofErr) if (err != noErr && err != eofErr)
goto ErrorExit; goto ErrorExit;
else
return pbAsync.pb.ioParam.ioActCount; return pbAsync.pb.ioParam.ioActCount;
ErrorExit: ErrorExit:
me->md.osErrCode = err; me->md.osErrCode = err;
_MD_SetError(err); _MD_SetError(err);
return -1; return -1;
} }
/* /*