mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-02-09 00:11:44 +00:00
Made NS_BASE_STREAM_WOULD_BLOCK a failure code (for JS). Reduced socket transport buffer size. Fixed ABBA deadlock when calling OnEmpty in pipe code (bug#12870).
This commit is contained in:
parent
5a36ea1109
commit
efb0c1cd5d
@ -446,7 +446,8 @@ nsresult nsSocketTransport::Process(PRInt16 aSelectFlags)
|
||||
}
|
||||
}
|
||||
// Process the write request...
|
||||
if (NS_SUCCEEDED(rv) && (GetWriteType() != eSocketWrite_None)) {
|
||||
if ((NS_SUCCEEDED(rv) || rv == NS_BASE_STREAM_WOULD_BLOCK)
|
||||
&& (GetWriteType() != eSocketWrite_None)) {
|
||||
rv = doWrite(aSelectFlags);
|
||||
if (NS_OK == rv) {
|
||||
SetFlag(eSocketWrite_Done);
|
||||
@ -472,12 +473,12 @@ nsresult nsSocketTransport::Process(PRInt16 aSelectFlags)
|
||||
if (NS_OK == rv) {
|
||||
mCurrentState = gStateTable[mOperation][mCurrentState];
|
||||
}
|
||||
else if (NS_FAILED(rv)) {
|
||||
mCurrentState = eSocketState_Error;
|
||||
}
|
||||
else if (NS_BASE_STREAM_WOULD_BLOCK == rv) {
|
||||
done = PR_TRUE;
|
||||
}
|
||||
else if (NS_FAILED(rv)) {
|
||||
mCurrentState = eSocketState_Error;
|
||||
}
|
||||
//
|
||||
// Any select flags are *only* valid the first time through the loop...
|
||||
//
|
||||
@ -1011,7 +1012,7 @@ nsresult nsSocketTransport::doWriteFromBuffer(PRUint32 *aCount)
|
||||
mSelectFlags &= (~PR_POLL_WRITE);
|
||||
rv = NS_OK;
|
||||
}
|
||||
else if (NS_SUCCEEDED(rv)) {
|
||||
else if (NS_SUCCEEDED(rv) || rv == NS_BASE_STREAM_WOULD_BLOCK) {
|
||||
//
|
||||
// If the buffer is empty, then notify the reader and stop polling
|
||||
// for write until there is data in the buffer. See the OnWrite()
|
||||
@ -1062,7 +1063,7 @@ nsresult nsSocketTransport::doWriteFromStream(PRUint32 *aCount)
|
||||
#else
|
||||
rv = mWriteFromStream->Read(gIOBuffer, maxBytesToRead, &bytesRead);
|
||||
#endif
|
||||
if (NS_SUCCEEDED(rv) && bytesRead) {
|
||||
if ((NS_SUCCEEDED(rv) || rv == NS_BASE_STREAM_WOULD_BLOCK) && bytesRead) {
|
||||
// Update the counters...
|
||||
*aCount += bytesRead;
|
||||
if (mWriteCount > 0) {
|
||||
@ -1435,8 +1436,8 @@ nsSocketTransport::AsyncRead(PRUint32 startPosition, PRInt32 readCount,
|
||||
rv = NS_NewPipe(getter_AddRefs(mReadPipeIn),
|
||||
getter_AddRefs(mReadPipeOut),
|
||||
this, // nsIPipeObserver
|
||||
MAX_IO_BUFFER_SIZE/2,
|
||||
2*MAX_IO_BUFFER_SIZE);
|
||||
NS_SOCKET_TRANSPORT_SEGMENT_SIZE,
|
||||
NS_SOCKET_TRANSPORT_BUFFER_SIZE);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
rv = mReadPipeIn->SetNonBlocking(PR_TRUE);
|
||||
}
|
||||
@ -1593,8 +1594,8 @@ nsSocketTransport::OpenInputStream(PRUint32 startPosition, PRInt32 readCount,
|
||||
rv = NS_NewPipe(getter_AddRefs(mReadPipeIn),
|
||||
getter_AddRefs(mReadPipeOut),
|
||||
this, // nsIPipeObserver
|
||||
MAX_IO_BUFFER_SIZE/2,
|
||||
2*MAX_IO_BUFFER_SIZE);
|
||||
NS_SOCKET_TRANSPORT_SEGMENT_SIZE,
|
||||
NS_SOCKET_TRANSPORT_BUFFER_SIZE);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
rv = mReadPipeOut->SetNonBlocking(PR_TRUE);
|
||||
*result = mReadPipeIn;
|
||||
@ -1656,7 +1657,8 @@ nsSocketTransport::OpenOutputStream(PRUint32 startPosition, nsIOutputStream* *re
|
||||
#else
|
||||
rv = NS_NewPipe(getter_AddRefs(in), getter_AddRefs(out),
|
||||
this, // nsIPipeObserver
|
||||
MAX_IO_BUFFER_SIZE, MAX_IO_BUFFER_SIZE);
|
||||
NS_SOCKET_TRANSPORT_SEGMENT_SIZE,
|
||||
NS_SOCKET_TRANSPORT_BUFFER_SIZE);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
rv = in->SetNonBlocking(PR_TRUE);
|
||||
}
|
||||
|
@ -34,6 +34,9 @@
|
||||
#include "nsIPipe.h"
|
||||
#define NSPIPE2
|
||||
|
||||
#define NS_SOCKET_TRANSPORT_SEGMENT_SIZE (4*1024)
|
||||
#define NS_SOCKET_TRANSPORT_BUFFER_SIZE (64*1024)
|
||||
|
||||
//
|
||||
// This is the size of the global buffer used by all nsSocketTransport
|
||||
// instances when reading from or writing to the network.
|
||||
|
@ -669,13 +669,6 @@ nsFileChannel::Process(void)
|
||||
if (mReadFixedAmount)
|
||||
mAmount -= amt; // subtract off the amount we just read from mAmount.
|
||||
if (NS_FAILED(mStatus)) goto error;
|
||||
if (mStatus == NS_BASE_STREAM_WOULD_BLOCK || amt == 0) {
|
||||
// Our nsIPipeObserver will have been called from WriteFrom
|
||||
// which in turn calls Suspend, so we should end up suspending
|
||||
// this file channel.
|
||||
Suspend();
|
||||
return;
|
||||
}
|
||||
|
||||
// and feed the buffer to the application via the buffer stream:
|
||||
if (mListener) {
|
||||
|
@ -41,8 +41,6 @@ interface nsIBaseStream : nsISupports
|
||||
/// For unichar streams
|
||||
#define NS_BASE_STREAM_BAD_CONVERSION NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_BASE, 6)
|
||||
|
||||
#define NS_BASE_STREAM_WOULD_BLOCK NS_ERROR_GENERATE_SUCCESS(NS_ERROR_MODULE_BASE, 7)
|
||||
|
||||
#define NS_BASE_STREAM_FULL NS_ERROR_GENERATE_SUCCESS(NS_ERROR_MODULE_BASE, 8)
|
||||
#define NS_BASE_STREAM_WOULD_BLOCK NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_BASE, 7)
|
||||
//@}
|
||||
%}
|
||||
|
@ -323,23 +323,18 @@ nsPipe::nsPipeInputStream::GetLength(PRUint32 *result)
|
||||
nsAutoCMonitor mon(pipe);
|
||||
|
||||
PRUint32 len = pipe->mBuffer.GetSize();
|
||||
if (pipe->mReadCursor) {
|
||||
char* end = (pipe->mReadLimit == pipe->mWriteLimit)
|
||||
? pipe->mWriteCursor
|
||||
: pipe->mReadLimit;
|
||||
len -= pipe->mBuffer.GetSegmentSize() - (end - pipe->mReadCursor);
|
||||
}
|
||||
// if (pipe->mWriteCursor)
|
||||
//len -= pipe->mWriteLimit - pipe->mWriteCursor;
|
||||
if (pipe->mReadCursor)
|
||||
len -= pipe->mBuffer.GetSegmentSize() - (pipe->mReadLimit - pipe->mReadCursor);
|
||||
if (pipe->mWriteCursor)
|
||||
len -= pipe->mWriteLimit - pipe->mWriteCursor;
|
||||
|
||||
if (result)
|
||||
*result = len;
|
||||
*result = len;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsPipe::nsPipeInputStream::ReadSegments(nsWriteSegmentFun writer,
|
||||
void* closure,
|
||||
void* closure,
|
||||
PRUint32 count,
|
||||
PRUint32 *readCount)
|
||||
{
|
||||
@ -360,11 +355,13 @@ nsPipe::nsPipeInputStream::ReadSegments(nsWriteSegmentFun writer,
|
||||
if (*readCount > 0 || NS_FAILED(rv))
|
||||
goto done; // don't Fill if we've got something
|
||||
if (pipe->mObserver) {
|
||||
PR_CExitMonitor(pipe);
|
||||
rv = pipe->mObserver->OnEmpty(pipe);
|
||||
PR_CEnterMonitor(pipe);
|
||||
if (NS_FAILED(rv)) goto done;
|
||||
}
|
||||
rv = Fill();
|
||||
if (rv == NS_BASE_STREAM_WOULD_BLOCK || NS_FAILED(rv))
|
||||
if (/*rv == NS_BASE_STREAM_WOULD_BLOCK || */NS_FAILED(rv))
|
||||
goto done;
|
||||
// else we filled the pipe, so go around again
|
||||
continue;
|
||||
@ -375,18 +372,18 @@ nsPipe::nsPipeInputStream::ReadSegments(nsWriteSegmentFun writer,
|
||||
PRUint32 writeCount;
|
||||
rv = writer(closure, readBuffer, *readCount, readBufferLen, &writeCount);
|
||||
NS_ASSERTION(rv != NS_BASE_STREAM_EOF, "Write should not return EOF");
|
||||
if (NS_FAILED(rv))
|
||||
goto done;
|
||||
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))
|
||||
if (/*rv == NS_BASE_STREAM_WOULD_BLOCK || */NS_FAILED(rv))
|
||||
goto done;
|
||||
// else we filled the pipe, so go around again
|
||||
continue;
|
||||
}
|
||||
if (NS_FAILED(rv))
|
||||
goto done;
|
||||
NS_ASSERTION(writeCount <= readBufferLen, "writer returned bad writeCount");
|
||||
readBuffer += writeCount;
|
||||
readBufferLen -= writeCount;
|
||||
@ -399,7 +396,9 @@ nsPipe::nsPipeInputStream::ReadSegments(nsWriteSegmentFun writer,
|
||||
pipe->mReadLimit = nsnull;
|
||||
PRBool empty = pipe->mBuffer.DeleteFirstSegment();
|
||||
if (empty && pipe->mObserver) {
|
||||
PR_CExitMonitor(pipe);
|
||||
rv = pipe->mObserver->OnEmpty(pipe);
|
||||
PR_CEnterMonitor(pipe);
|
||||
if (NS_FAILED(rv))
|
||||
goto done;
|
||||
}
|
||||
@ -610,11 +609,13 @@ nsPipe::nsPipeOutputStream::WriteSegments(nsReadSegmentFun reader,
|
||||
goto done;
|
||||
if (writeBufLen == 0) {
|
||||
if (pipe->mObserver && *writeCount == 0) {
|
||||
PR_CExitMonitor(pipe);
|
||||
rv = pipe->mObserver->OnFull(pipe);
|
||||
PR_CEnterMonitor(pipe);
|
||||
if (NS_FAILED(rv)) goto done;
|
||||
}
|
||||
rv = Flush();
|
||||
if (rv == NS_BASE_STREAM_WOULD_BLOCK || NS_FAILED(rv))
|
||||
if (/*rv == NS_BASE_STREAM_WOULD_BLOCK || */NS_FAILED(rv))
|
||||
goto done;
|
||||
// else we flushed, so go around again
|
||||
continue;
|
||||
@ -624,21 +625,21 @@ nsPipe::nsPipeOutputStream::WriteSegments(nsReadSegmentFun reader,
|
||||
while (writeBufLen > 0) {
|
||||
PRUint32 readCount = 0;
|
||||
rv = reader(closure, writeBuf, *writeCount, writeBufLen, &readCount);
|
||||
if (NS_FAILED(rv)) {
|
||||
// save the failure condition so that we can get it again later
|
||||
pipe->mCondition = rv;
|
||||
goto done;
|
||||
}
|
||||
if (readCount == 0) {
|
||||
if (rv == NS_BASE_STREAM_WOULD_BLOCK || readCount == 0) {
|
||||
// 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 (rv2 == NS_BASE_STREAM_WOULD_BLOCK || NS_FAILED(rv2))
|
||||
if (/*rv2 == NS_BASE_STREAM_WOULD_BLOCK || */NS_FAILED(rv2))
|
||||
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;
|
||||
}
|
||||
NS_ASSERTION(readCount <= writeBufLen, "reader returned bad readCount");
|
||||
writeBuf += readCount;
|
||||
writeBufLen -= readCount;
|
||||
|
Loading…
x
Reference in New Issue
Block a user