diff options
author | sfraser%netscape.com <devnull@localhost> | 2001-09-20 00:08:36 +0000 |
---|---|---|
committer | sfraser%netscape.com <devnull@localhost> | 2001-09-20 00:08:36 +0000 |
commit | 0ddfc03c858d5887a4a2ee0718b2e7e18b35430a (patch) | |
tree | 91f5753e4742000c47b368ab2870bf01d279cdfe | |
parent | d04169c8538de1960dced2437569177a769fdc2b (diff) | |
download | nspr-hg-0ddfc03c858d5887a4a2ee0718b2e7e18b35430a.tar.gz |
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.
-rw-r--r-- | pr/src/md/mac/macio.c | 57 |
1 files changed, 27 insertions, 30 deletions
diff --git a/pr/src/md/mac/macio.c b/pr/src/md/mac/macio.c index 9bc408dd..99bad41f 100644 --- a/pr/src/md/mac/macio.c +++ b/pr/src/md/mac/macio.c @@ -91,7 +91,7 @@ typedef struct ExtendedParamBlock ExtendedParamBlock; static void AsyncIOCompletion (ExtendedParamBlock *pbAsyncPtr) { _PRCPU *cpu = _PR_MD_CURRENT_CPU(); - PRThread *thread = pbAsyncPtr->thread; + PRThread *thread = pbAsyncPtr->thread; if (_PR_MD_GET_INTSOFF()) { cpu->u.missed[cpu->where] |= _PR_MISSED_IO; @@ -247,9 +247,9 @@ PRInt32 ReadWriteProc(PRFileDesc *fd, void *buf, PRUint32 bytes, IOOperation op) { PRInt32 refNum = fd->secret->md.osfd; OSErr err; - ExtendedParamBlock pbAsync; + ExtendedParamBlock pbAsync; 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 */ /* note, if a user chooses "seek" or the like as an operation in another function */ @@ -270,12 +270,13 @@ PRInt32 ReadWriteProc(PRFileDesc *fd, void *buf, PRUint32 bytes, IOOperation op) } return (bytes); - } else { static IOCompletionUPP sCompletionUPP = NULL; + PRBool doingAsync = PR_FALSE; + /* allocate the callback Universal Procedure Pointer (UPP). This actually allocates a 32 byte Ptr in the heap, so only do this once */ @@ -296,9 +297,11 @@ PRInt32 ReadWriteProc(PRFileDesc *fd, void *buf, PRUint32 bytes, IOOperation op) /* ** Issue the async read call and wait for the io semaphore associated ** 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; if (op == READ_ASYNC) { @@ -308,39 +311,33 @@ PRInt32 ReadWriteProc(PRFileDesc *fd, void *buf, PRUint32 bytes, IOOperation op) */ if ( bytes > 20480L ) { - err = PBReadAsync(&pbAsync.pb); - if (err != noErr && err != eofErr) - goto ErrorExit; + doingAsync = PR_TRUE; + me->io_pending = PR_TRUE; - me->io_pending = PR_TRUE; /* Only mark thread io pending if async call worked */ + (void)PBReadAsync(&pbAsync.pb); } else { - (void) PBReadSync(&pbAsync.pb); - /* - ** 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 - ** threading - */ - pbAsync.pb.ioParam.ioResult = 0; + pbAsync.pb.ioParam.ioCompletion = NULL; + me->io_pending = PR_FALSE; + + err = PBReadSync(&pbAsync.pb); + if (err != noErr && err != eofErr) + goto ErrorExit; } } else { + doingAsync = PR_TRUE; + me->io_pending = PR_TRUE; + /* writes are currently always async */ - err = 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; + (void)PBWriteAsync(&pbAsync.pb); } - /* See if the i/o call is still pending before we actually yield */ - if (pbAsync.pb.ioParam.ioResult == 1) + if (doingAsync) { 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; @@ -350,13 +347,13 @@ PRInt32 ReadWriteProc(PRFileDesc *fd, void *buf, PRUint32 bytes, IOOperation op) err = pbAsync.pb.ioParam.ioResult; if (err != noErr && err != eofErr) goto ErrorExit; - else - return pbAsync.pb.ioParam.ioActCount; + + return pbAsync.pb.ioParam.ioActCount; ErrorExit: me->md.osErrCode = err; _MD_SetError(err); - return -1; + return -1; } /* |