diff options
author | dormando <dormando@rydia.net> | 2020-03-25 14:02:11 -0700 |
---|---|---|
committer | dormando <dormando@rydia.net> | 2020-03-25 14:02:11 -0700 |
commit | 5174ef33576f461d43f43b2019f5e10655b4c78f (patch) | |
tree | e42163e06d0622491cf1f80e1822192d9a07b7aa /memcached.c | |
parent | 79140c7033519cdbcc9d59f08425ddda0a79bff7 (diff) | |
download | memcached-5174ef33576f461d43f43b2019f5e10655b4c78f.tar.gz |
restart: fix rare segfault on shutdown
Client connections were being closed and cleaned up after worker
threads exit. In 2018 a patch went in to have the worker threads
actually free their event base when stopped. If your system is strict
enough (which is apparently none out of the dozen+ systems we've tested
against!) it will segfault on invalid memory.
This change leaves the workers hung while they wait for connections to
be centrally closed. I would prefer to have each worker thread close
its own connections for speed if nothing else, but we still need to
close the listener connections and any connections currently open in
side channels.
Much apprecation to darix for helping narrow this down, as it presented
as a wiped stack that only appeared in a specific build environment on
a specific linux distribution.
Hopefully with all of the valgrind noise fixes lately we can start
running it more regularly and spot these early.
Diffstat (limited to 'memcached.c')
-rw-r--r-- | memcached.c | 19 |
1 files changed, 12 insertions, 7 deletions
diff --git a/memcached.c b/memcached.c index 2592b3f..dd52dd0 100644 --- a/memcached.c +++ b/memcached.c @@ -939,6 +939,18 @@ static void conn_close(conn *c) { return; } +// Since some connections might be off on side threads and some are managed as +// listeners we need to walk through them all from a central point. +// Must be called with all worker threads hung or in the process of closing. +void conn_close_all(void) { + int i; + for (i = 0; i < max_fds; i++) { + if (conns[i] && conns[i]->state != conn_closed) { + conn_close(conns[i]); + } + } +} + /** * Convert a state name to a human readable form. */ @@ -10126,13 +10138,6 @@ int main (int argc, char **argv) { fprintf(stderr, "Gracefully stopping\n"); stop_threads(); - int i; - // FIXME: make a function callable from threads.c - for (i = 0; i < max_fds; i++) { - if (conns[i] && conns[i]->state != conn_closed) { - conn_close(conns[i]); - } - } if (memory_file != NULL) { restart_mmap_close(); } |