summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordormando <dormando@rydia.net>2021-08-03 12:50:56 -0700
committerdormando <dormando@rydia.net>2021-08-09 17:09:08 -0700
commitf8a55c4731ab38b8c1a88cb7bf10fadc209fd78f (patch)
tree1f3d66e1904d931adadd39971624285122dc1be3
parent5d53b04240938654ecd38f2e609cd821e3a3723f (diff)
downloadmemcached-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.c9
-rw-r--r--t/error-extstore.t8
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
{