mon.Enter();
nsPipe::nsPipeOutputStream::WriteSegments(nsReadSegmentFun reader,                                          void* closure,                                          PRUint32 count,                                          PRUint32 *writeCount){    nsresult rv = NS_OK;#ifdef MASK_PREMATURE_STREAM_RELEASE    nsCOMPtr<nsIOutputStream> kungFuDeathGrip(this);#endif    nsPipe* pipe = GET_OUTPUTSTREAM_PIPE(this);    PRUint32 amt = count;    {        nsAutoMonitor mon(pipe->GetMonitor());        *writeCount = 0;        if (NS_FAILED(pipe->mCondition)            && pipe->mCondition != NS_BASE_STREAM_CLOSED) {            rv = pipe->mCondition;            goto done;        }        while (amt > 0) {            PRUint32 writeBufLen;            char* writeBuf;            rv = pipe->GetWriteSegment(&writeBuf, &writeBufLen);            if (NS_FAILED(rv))                goto done;            if (writeBufLen == 0) {                if (*writeCount > 0 && !mBlocking)                    goto done;                if (mObserver/* && *writeCount == 0*/) {                    mon.Exit();     // XXXbe avoid deadlock better                    rv = mObserver->OnFull(this);                    mon.Enter();                    if (NS_FAILED(rv)) goto done;                }                rv = Flush();                if (/*rv == NS_BASE_STREAM_WOULD_BLOCK || */NS_FAILED(rv))                    goto done;                // else we flushed, so go around again                continue;            }            writeBufLen = PR_MIN(writeBufLen, amt);            while (writeBufLen > 0) {                PRUint32 readCount = 0;                rv = reader(this, closure, writeBuf, *writeCount, writeBufLen, &readCount);                if (rv == NS_BASE_STREAM_WOULD_BLOCK) {                    NS_ASSERTION(readCount <= writeBufLen, "reader returned bad readCount");                    // XXX should not update counters if reader returned WOULD_BLOCK!!                    writeBuf += readCount;                    writeBufLen -= readCount;                    *writeCount += readCount;                    amt -= readCount;                    pipe->mWriteCursor += readCount;                    // The reader didn't have anything else to put in the buffer, so                    // call flush to notify the guy downstream, hoping that he'll somehow                    // wake up the guy upstream to eventually produce more data for us.                    nsresult rv2 = Flush();                    if (NS_FAILED(rv2)) {                        if (rv2 == NS_BASE_STREAM_WOULD_BLOCK)                            rv = pipe->mCondition;                        goto done;                    }                    // else we flushed, so go around again                    continue;                }                if (NS_FAILED(rv)) {                    // save the failure condition so that we can get it again later                    pipe->mCondition = rv;                    goto done;                }                if (readCount == 0) { // EOF                    pipe->mCondition = NS_BASE_STREAM_CLOSED;                    goto done;                }                NS_ASSERTION(readCount <= writeBufLen, "reader returned bad readCount");                writeBuf += readCount;                writeBufLen -= readCount;                *writeCount += readCount;                amt -= readCount;                pipe->mWriteCursor += readCount;            }            if (pipe->mWriteCursor == pipe->mWriteLimit) {                pipe->mWriteCursor =  nsnull;                pipe->mWriteLimit =  nsnull;            }        }      done:        if (mBlocking && rv == NS_BASE_STREAM_WOULD_BLOCK && *writeCount > 0) {            mon.Notify();       // wake up reader        }        ;    }   // exit monitor    if (mObserver && *writeCount > 0) {        mObserver->OnWrite(this, *writeCount);    }    NS_ASSERTION(*writeCount <= count, "wrote more than expected");    return *writeCount == 0 ? rv : NS_OK;}