multipath: fix shutdown crashes
authorBenjamin Marzinski <bmarzins@redhat.com>
Fri, 10 Feb 2012 18:10:11 +0000 (12:10 -0600)
committerChristophe Varoqui <christophe.varoqui@opensvc.com>
Sat, 11 Feb 2012 08:19:58 +0000 (09:19 +0100)
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 <bmarzins@redhat.com>
libmultipath/log_pthread.c
libmultipath/waiter.c
multipathd/main.c

index ed7b200..d701ba1 100644 (file)
@@ -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();
 
index 35c1e2b..974593c 100644 (file)
@@ -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);
 
index ee01ba4..1f95a2f 100644 (file)
@@ -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) {