mon.Enter();
nsPipe::nsPipeInputStream::ReadSegments(nsWriteSegmentFun writer,                                         void* closure,                                          PRUint32 count,                                        PRUint32 *readCount){    nsPipe* pipe = GET_INPUTSTREAM_PIPE(this);    nsAutoMonitor mon(pipe->GetMonitor());    nsresult rv = NS_OK;    PRUint32 readBufferLen;    const char* readBuffer;    *readCount = 0;    PRUint32 amt = count;    while (amt > 0) {        rv = pipe->GetReadSegment(0, &readBuffer, &readBufferLen);        if (NS_FAILED(rv))            goto done;        if (readBufferLen == 0) {            rv = pipe->mCondition;            if (*readCount > 0 || NS_FAILED(rv))                goto done;      // don't Fill if we've got something            if (mObserver) {                mon.Exit();     // XXXbe avoid deadlock better                rv = mObserver->OnEmpty(this);                mon.Enter();                if (NS_FAILED(rv)) goto done;            }            rv = Fill();            if (/*rv == NS_BASE_STREAM_WOULD_BLOCK || */NS_FAILED(rv))                 goto done;            // else we filled the pipe, so go around again            continue;        }        readBufferLen = PR_MIN(readBufferLen, amt);        while (readBufferLen > 0) {            PRUint32 writeCount = 0;            rv = writer(this, closure, readBuffer, *readCount, readBufferLen, &writeCount);            if (NS_FAILED(rv) && rv != NS_BASE_STREAM_WOULD_BLOCK)                goto done;            NS_ASSERTION(writeCount <= readBufferLen, "writer returned bad writeCount");#ifdef DEBUG            if (writeCount > 0 && rv == NS_BASE_STREAM_WOULD_BLOCK)                NS_WARNING("Invalid writer implementation: cannot write data and return WOULD_BLOCK");#endif            readBuffer += writeCount;            readBufferLen -= writeCount;            *readCount += writeCount;            amt -= writeCount;            pipe->mReadCursor += writeCount;            if (writeCount == 0 || rv == NS_BASE_STREAM_WOULD_BLOCK) {                rv = pipe->mCondition;                if (*readCount > 0 || NS_FAILED(rv))                    goto done;      // don't Fill if we've got something                rv = Fill();                if (/*rv == NS_BASE_STREAM_WOULD_BLOCK || */NS_FAILED(rv))                    goto done;                // else we filled the pipe, so go around again                continue;            }        }        if (pipe->mReadCursor == pipe->mReadLimit) {            pipe->mReadCursor = nsnull;            pipe->mReadLimit = nsnull;            PRBool empty = pipe->mBuffer.DeleteFirstSegment();            if (empty && mObserver) {                mon.Exit();     // XXXbe avoid deadlock better                rv = mObserver->OnEmpty(this);                mon.Enter();                mon.Notify();   // wake up writer                if (NS_FAILED(rv))                    goto done;            }        }        else if (pipe->mReadCursor == pipe->mWriteCursor) {            if (mObserver) {                mon.Exit();     // XXXbe avoid deadlock better                rv = mObserver->OnEmpty(this);                mon.Enter();                if (NS_FAILED(rv))                    goto done;            }        }    }  done:    if (mBlocking && rv == NS_BASE_STREAM_WOULD_BLOCK && *readCount > 0) {        mon.Notify();   // wake up writer    }    if (rv == NS_BASE_STREAM_CLOSED) {    // EOF        if (mObserver) {            nsCOMPtr<nsIInputStreamObserver> obs = mObserver;            mon.Exit();     // XXXbe avoid deadlock better            nsresult rv2 = obs->OnClose(this);            mon.Enter();            NS_ASSERTION(NS_SUCCEEDED(rv2), "OnClose failed");            // don't return error from OnClose -- its not our problem            mObserver = nsnull;       // so we don't call OnClose again        }        rv = NS_OK;    }    NS_ASSERTION(*readCount <= count, "read more than expected");    return *readCount == 0 ? rv : NS_OK;}