Bug 1371699 part 5. Fix IPCStreamSource's handling of async streams returning 0 from Available. r=bkelly

This aligns the code more closely with how the input stream pump works: 0
available bytes when the stream itself told us it's ready means the stream is at
the end.
This commit is contained in:
Boris Zbarsky 2017-06-13 16:16:55 -04:00
parent 5193353a61
commit 817f0609ac
2 changed files with 25 additions and 5 deletions

View File

@ -190,7 +190,7 @@ void
IPCStreamSource::Start()
{
NS_ASSERT_OWNINGTHREAD(IPCStreamSource);
DoRead();
DoRead(ReadReason::Starting);
}
void
@ -201,7 +201,7 @@ IPCStreamSource::StartDestroy()
}
void
IPCStreamSource::DoRead()
IPCStreamSource::DoRead(ReadReason aReadReason)
{
NS_ASSERT_OWNINGTHREAD(IPCStreamSource);
MOZ_ASSERT(mState == eActorConstructed);
@ -215,6 +215,15 @@ IPCStreamSource::DoRead()
static_assert(kMaxBytesPerMessage <= static_cast<uint64_t>(UINT32_MAX),
"kMaxBytesPerMessage must cleanly cast to uint32_t");
// Per the nsIInputStream API, having 0 bytes available in a stream is
// ambiguous. It could mean "no data yet, but some coming later" or it could
// mean "EOF" (end of stream).
//
// If we're just starting up, we can't distinguish between those two options.
// But if we're being notified that an async stream is ready, then the
// first Available() call returning 0 should really mean end of stream.
// Subsequent Available() calls, after we read some data, could mean anything.
bool noDataMeansEOF = (aReadReason == ReadReason::Notified);
while (true) {
// It should not be possible to transition to closed state without
// this loop terminating via a return.
@ -234,7 +243,11 @@ IPCStreamSource::DoRead()
}
if (available == 0) {
Wait();
if (noDataMeansEOF) {
OnEnd(rv);
} else {
Wait();
}
return;
}
@ -248,6 +261,9 @@ IPCStreamSource::DoRead()
MOZ_ASSERT_IF(NS_FAILED(rv), bytesRead == 0);
buffer.SetLength(bytesRead);
// After this point, having no data tells us nothing about EOF.
noDataMeansEOF = false;
// If we read any data from the stream, send it across.
if (!buffer.IsEmpty()) {
SendData(buffer);
@ -291,7 +307,7 @@ IPCStreamSource::OnStreamReady(Callback* aCallback)
MOZ_ASSERT(aCallback == mCallback);
mCallback->ClearSource();
mCallback = nullptr;
DoRead();
DoRead(ReadReason::Notified);
}
void

View File

@ -121,7 +121,11 @@ private:
virtual bool
Notify(dom::workers::Status aStatus) override;
void DoRead();
enum class ReadReason {
Starting, // We're trying to read because we just started off.
Notified // We're trying to read because the streams said it's ready.
};
void DoRead(ReadReason aReadReason);
void Wait();