mirror of
https://github.com/matrix-construct/construct
synced 2024-06-11 06:28:55 +02:00
ircd::server: Fix bug when overrun discarded in cancellation buffer.
This commit is contained in:
parent
d2b79dbb04
commit
7d4cf45f01
|
@ -44,7 +44,7 @@ struct ircd::server::link
|
|||
void discard_read();
|
||||
const_buffer read(const mutable_buffer &buf);
|
||||
const_buffer process_read_next(const const_buffer &, tag &, bool &done);
|
||||
bool process_read(const_buffer &);
|
||||
bool process_read(const_buffer &, unique_buffer<mutable_buffer> &);
|
||||
void handle_readable_success();
|
||||
void handle_readable(const error_code &) noexcept;
|
||||
void wait_readable();
|
||||
|
|
|
@ -2192,10 +2192,16 @@ ircd::server::link::handle_readable_success()
|
|||
}
|
||||
|
||||
// Data pointed to by overrun will remain intact between iterations
|
||||
// because this loop isn't executing in any ircd::ctx.
|
||||
// because this loop isn't executing in any ircd::ctx. Since the buffers
|
||||
// we're using are supplied by users in other ctxs they will continue to
|
||||
// exist as this loop continues to the next tags. There is one exception
|
||||
// case though: canceled requests have their buffers free'ed when the tag
|
||||
// is pop'ed from this link's queue, because the user is gone; the scratch
|
||||
// buffer is maintained between iterations in that case.
|
||||
unique_buffer<mutable_buffer> scratch;
|
||||
const_buffer overrun; do
|
||||
{
|
||||
if(!process_read(overrun))
|
||||
if(!process_read(overrun, scratch))
|
||||
{
|
||||
wait_readable();
|
||||
return;
|
||||
|
@ -2209,7 +2215,8 @@ ircd::server::link::handle_readable_success()
|
|||
|
||||
/// Process as many read operations for one tag as possible
|
||||
bool
|
||||
ircd::server::link::process_read(const_buffer &overrun)
|
||||
ircd::server::link::process_read(const_buffer &overrun,
|
||||
unique_buffer<mutable_buffer> &scratch)
|
||||
try
|
||||
{
|
||||
assert(peer);
|
||||
|
@ -2254,6 +2261,22 @@ try
|
|||
return done;
|
||||
}
|
||||
|
||||
// Branch to handle overrun out of a cancelled tag which needs its data
|
||||
// copied to scratch before being pop'ed off the queue; fairly rare case.
|
||||
// If the tag is not in a canceled state, the overrun will point to valid
|
||||
// data for the next tag even after being popped off the queue.
|
||||
if(!empty(overrun) && tag.canceled())
|
||||
{
|
||||
// Copy into new buffer before trashing the old buffer in case each
|
||||
// tag being processed here is just windowing down on the same data
|
||||
// nagled together at the first tag.
|
||||
unique_buffer<mutable_buffer> _scratch(overrun);
|
||||
scratch = std::move(_scratch);
|
||||
overrun = scratch;
|
||||
assert(!empty(overrun));
|
||||
assert(!empty(scratch));
|
||||
}
|
||||
|
||||
peer->handle_tag_done(*this, tag);
|
||||
assert(!queue.empty());
|
||||
queue.pop_front();
|
||||
|
|
Loading…
Reference in a new issue