From 03ec4efe8775f0ca076df3fb85b9defab4ffad30 Mon Sep 17 00:00:00 2001 From: Benjamin Marzinski Date: Fri, 10 Feb 2012 12:10:11 -0600 Subject: [PATCH] multipath: fix shutdown crashes A number of processes don't reach a pthread cancellation point before they use the pathvec or mpvec vectors, after they've locked the vecs lock. This can cause crashes on shutdown, since these vectors are deallocated. Also, the log thread accesses a number of resources which may have been deallocated during shutdown without holding any locks. This patch avoids these issues by adding pthread_testcancel() checks after acquiring the vecs lock, and having the child process make sure the log thread has exitted before deallocating the resources. Signed-off-by: Benjamin Marzinski --- libmultipath/log_pthread.c | 1 + libmultipath/waiter.c | 1 + multipathd/main.c | 6 +++++- 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/libmultipath/log_pthread.c b/libmultipath/log_pthread.c index ed7b200..d701ba1 100644 --- a/libmultipath/log_pthread.c +++ b/libmultipath/log_pthread.c @@ -87,6 +87,7 @@ void log_thread_stop (void) pthread_mutex_lock(logq_lock); pthread_cancel(log_thr); pthread_mutex_unlock(logq_lock); + pthread_join(log_thr, NULL); flush_logqueue(); diff --git a/libmultipath/waiter.c b/libmultipath/waiter.c index 35c1e2b..974593c 100644 --- a/libmultipath/waiter.c +++ b/libmultipath/waiter.c @@ -157,6 +157,7 @@ int waiteventloop (struct event_thread *waiter) */ pthread_cleanup_push(cleanup_lock, &waiter->vecs->lock); lock(waiter->vecs->lock); + pthread_testcancel(); r = update_multipath(waiter->vecs, waiter->mapname, 1); lock_cleanup_pop(waiter->vecs->lock); diff --git a/multipathd/main.c b/multipathd/main.c index ee01ba4..1f95a2f 100644 --- a/multipathd/main.c +++ b/multipathd/main.c @@ -741,6 +741,7 @@ uxsock_trigger (char * str, char ** reply, int * len, void * trigger_data) pthread_cleanup_push(cleanup_lock, &vecs->lock); lock(vecs->lock); + pthread_testcancel(); r = parse_cmd(str, reply, len, vecs); @@ -793,7 +794,9 @@ uev_trigger (struct uevent * uev, void * trigger_data) if (uev_discard(uev->devpath)) return 0; + pthread_cleanup_push(cleanup_lock, &vecs->lock); lock(vecs->lock); + pthread_testcancel(); /* * device map event @@ -833,7 +836,7 @@ uev_trigger (struct uevent * uev, void * trigger_data) } out: - unlock(vecs->lock); + lock_cleanup_pop(vecs->lock); return r; } @@ -1287,6 +1290,7 @@ checkerloop (void *ap) block_signal(SIGHUP, &old); pthread_cleanup_push(cleanup_lock, &vecs->lock); lock(vecs->lock); + pthread_testcancel(); condlog(4, "tick"); if (vecs->pathvec) { -- 2.34.1