diff options
author | dormando <dormando@rydia.net> | 2021-08-03 12:50:56 -0700 |
---|---|---|
committer | dormando <dormando@rydia.net> | 2021-08-09 17:09:08 -0700 |
commit | f8a55c4731ab38b8c1a88cb7bf10fadc209fd78f (patch) | |
tree | 1f3d66e1904d931adadd39971624285122dc1be3 | |
parent | 5d53b04240938654ecd38f2e609cd821e3a3723f (diff) | |
download | memcached-f8a55c4731ab38b8c1a88cb7bf10fadc209fd78f.tar.gz |
core: fix hang bug in extstore
The previous commit (IO queue submit if queue is not NULL, instead of queue
count) exposed an apparent long standing bug in extstore: do an
ascii-multiget request with multiple keys, but one too-long or otherwise
garbage key. This will reset the queue count to 0 but leave a stack
pointer to now freed memory.
The next request could infinite loop, as this test was causing.
-rw-r--r-- | memcached.c | 9 | ||||
-rw-r--r-- | t/error-extstore.t | 8 |
2 files changed, 17 insertions, 0 deletions
diff --git a/memcached.c b/memcached.c index c344359..e3bf3c3 100644 --- a/memcached.c +++ b/memcached.c @@ -585,6 +585,14 @@ void conn_io_queue_setup(conn *c) { } } +// To be called from conn_release_items to ensure the stack ptrs are reset. +static void conn_io_queue_reset(conn *c) { + for (io_queue_t *q = c->io_queues; q->type != IO_QUEUE_NONE; q++) { + assert(q->count == 0); + q->stack_ctx = NULL; + } +} + io_queue_cb_t *thread_io_queue_get(LIBEVENT_THREAD *t, int type) { io_queue_cb_t *q = t->io_queues; while (q->type != IO_QUEUE_NONE) { @@ -842,6 +850,7 @@ void conn_release_items(conn *c) { } resp = resp_finish(c, resp); } + conn_io_queue_reset(c); } } diff --git a/t/error-extstore.t b/t/error-extstore.t index 6df1528..ed196bc 100644 --- a/t/error-extstore.t +++ b/t/error-extstore.t @@ -68,6 +68,14 @@ wait_for_ext(); cmp_ok($stats->{get_aborted_extstore}, '>', 1, 'some extstore queries aborted'); } +# Infinite loop: if we aborted some extstore requests, the next request would hang +# the daemon. +{ + my $size = 3000 * 1024; + my $data = "x" x $size; + mem_get_is($sock, "foo1", $data); +} + # Disable automatic page balancing, then move enough pages that the large # items can no longer be loaded from extstore { |