mirror of
https://github.com/RGBCube/serenity
synced 2025-07-27 12:07:45 +00:00
LibCore: Make BufferedHelper::read() block at most once per read
The previous method could block multiple times, leading to a completely
stuck/deadlocked read() call, and it could also consume data without
telling the user about it, which is Not A Good Thing ™️.
This patch makes it block at most once, and fixes loading HTTP pages
with LibHTTP :^)
This commit is contained in:
parent
17a3dd23f4
commit
d3c25b8ea2
1 changed files with 22 additions and 16 deletions
|
@ -521,6 +521,10 @@ public:
|
||||||
if (!buffer.size())
|
if (!buffer.size())
|
||||||
return Error::from_errno(ENOBUFS);
|
return Error::from_errno(ENOBUFS);
|
||||||
|
|
||||||
|
// Fill the internal buffer if it has run dry.
|
||||||
|
if (m_buffered_size == 0)
|
||||||
|
TRY(populate_read_buffer());
|
||||||
|
|
||||||
// Let's try to take all we can from the buffer first.
|
// Let's try to take all we can from the buffer first.
|
||||||
size_t buffer_nread = 0;
|
size_t buffer_nread = 0;
|
||||||
if (m_buffered_size > 0) {
|
if (m_buffered_size > 0) {
|
||||||
|
@ -539,22 +543,9 @@ public:
|
||||||
m_buffered_size -= amount_to_take;
|
m_buffered_size -= amount_to_take;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the buffer satisfied the request, then we need not continue.
|
|
||||||
if (buffer_nread == buffer.size()) {
|
|
||||||
return buffer_nread;
|
return buffer_nread;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Otherwise, let's try an extra read just in case there's something
|
|
||||||
// in our receive buffer.
|
|
||||||
auto stream_nread = TRY(stream().read(buffer.slice(buffer_nread)));
|
|
||||||
|
|
||||||
// Fill the internal buffer if it has run dry.
|
|
||||||
if (m_buffered_size == 0)
|
|
||||||
TRY(populate_read_buffer());
|
|
||||||
|
|
||||||
return buffer_nread + stream_nread;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reads into the buffer until \n is encountered.
|
// Reads into the buffer until \n is encountered.
|
||||||
// The size of the Bytes object is the maximum amount of bytes that will be
|
// The size of the Bytes object is the maximum amount of bytes that will be
|
||||||
// read. Returns the amount of bytes read.
|
// read. Returns the amount of bytes read.
|
||||||
|
@ -703,8 +694,23 @@ private:
|
||||||
return ReadonlyBytes {};
|
return ReadonlyBytes {};
|
||||||
|
|
||||||
auto fillable_slice = m_buffer.span().slice(m_buffered_size);
|
auto fillable_slice = m_buffer.span().slice(m_buffered_size);
|
||||||
auto nread = TRY(stream().read(fillable_slice));
|
size_t nread = 0;
|
||||||
m_buffered_size += nread;
|
do {
|
||||||
|
auto result = stream().read(fillable_slice);
|
||||||
|
if (result.is_error()) {
|
||||||
|
if (!result.error().is_errno())
|
||||||
|
return result.error();
|
||||||
|
if (result.error().code() == EINTR)
|
||||||
|
continue;
|
||||||
|
if (result.error().code() == EAGAIN)
|
||||||
|
break;
|
||||||
|
return result.error();
|
||||||
|
}
|
||||||
|
auto read_size = result.value();
|
||||||
|
m_buffered_size += read_size;
|
||||||
|
nread += read_size;
|
||||||
|
break;
|
||||||
|
} while (true);
|
||||||
return fillable_slice.slice(0, nread);
|
return fillable_slice.slice(0, nread);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue