зеркало из https://github.com/mozilla/gecko-dev.git
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:
Родитель
1856815ff1
Коммит
1498bf8a26
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
Загрузка…
Ссылка в новой задаче