Bug 1663718 - Don't put too much data in buffer when the data can't be written to socket r=dragana

The main reason we used too much memory is that we ignore the `NS_BASE_STREAM_WOULD_BLOCK` returned from socket output stream.
When the output stream is blocked, all the data is stored in the output queue and make the memory usage high.

Differential Revision: https://phabricator.services.mozilla.com/D89563
This commit is contained in:
Kershaw Chang 2020-09-11 08:44:07 +00:00
Родитель 11b8b5a61b
Коммит 40ec8af428
5 изменённых файлов: 33 добавлений и 1 удалений

Просмотреть файл

@ -3862,6 +3862,10 @@ void WebSocketChannel::DoEnqueueOutgoingMessage() {
mHdrOut, mHdrOutSize, (uint8_t*)mCurrentOut->BeginReading(),
mCurrentOut->Length());
if (rv == NS_BASE_STREAM_WOULD_BLOCK) {
return;
}
LOG(("WebSocketChannel::DoEnqueueOutgoingMessage: rv %" PRIx32 "\n",
static_cast<uint32_t>(rv)));
@ -3924,6 +3928,12 @@ WebSocketChannel::OnDataReceived(uint8_t* aData, uint32_t aCount) {
return ProcessInput(aData, aCount);
}
NS_IMETHODIMP
WebSocketChannel::OnReadyToSendData() {
DoEnqueueOutgoingMessage();
return NS_OK;
}
} // namespace net
} // namespace mozilla

Просмотреть файл

@ -174,6 +174,12 @@ WebSocketConnectionChild::OnDataReceived(uint8_t* aData, uint32_t aCount) {
return NS_OK;
}
NS_IMETHODIMP
WebSocketConnectionChild::OnReadyToSendData() {
// TODO: implement flow control between parent and socket process.
return NS_OK;
}
void WebSocketConnectionChild::ActorDestroy(ActorDestroyReason aWhy) {
LOG(("WebSocketConnectionChild::ActorDestroy %p\n", this));
if (mConnection) {

Просмотреть файл

@ -71,4 +71,9 @@ interface nsIWebSocketConnectionListener : nsISupports
void onDataReceived([array, size_is(dataLength)]in uint8_t data,
in unsigned long dataLength);
/**
* Called to inform the listener that the outgoing data is ready to write.
*/
void onReadyToSendData();
};

Просмотреть файл

@ -20,7 +20,8 @@ nsWebSocketConnection::nsWebSocketConnection(
mSocketIn(aInputStream),
mSocketOut(aOutputStream),
mWriteOffset(0),
mStartReadingCalled(false) {
mStartReadingCalled(false),
mOutputStreamBlocked(false) {
LOG(("nsWebSocketConnection ctor %p\n", this));
}
@ -105,6 +106,10 @@ nsWebSocketConnection::EnqueueOutputData(const uint8_t* aHdrBuf,
mSocketOut->AsyncWait(this, 0, 0, mEventTarget);
}
if (mOutputStreamBlocked) {
return NS_BASE_STREAM_WOULD_BLOCK;
}
return NS_OK;
}
@ -215,6 +220,8 @@ nsWebSocketConnection::OnOutputStreamReady(nsIAsyncOutputStream* aStream) {
return NS_OK;
}
mOutputStreamBlocked = false;
while (!mOutputQueue.empty()) {
const OutputData& data = mOutputQueue.front();
@ -230,6 +237,7 @@ nsWebSocketConnection::OnOutputStreamReady(nsIAsyncOutputStream* aStream) {
if (rv == NS_BASE_STREAM_WOULD_BLOCK) {
mSocketOut->AsyncWait(this, 0, 0, mEventTarget);
mOutputStreamBlocked = true;
return NS_OK;
}
@ -248,5 +256,7 @@ nsWebSocketConnection::OnOutputStreamReady(nsIAsyncOutputStream* aStream) {
}
}
Unused << mListener->OnReadyToSendData();
return NS_OK;
}

Просмотреть файл

@ -60,6 +60,7 @@ class nsWebSocketConnection : public nsIWebSocketConnection,
size_t mWriteOffset;
std::list<OutputData> mOutputQueue;
bool mStartReadingCalled;
bool mOutputStreamBlocked;
};
} // namespace net