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 ed7b200ccf9c7e5dd3ae50617fe8481a3e213fc8..d701ba180c745b5e5ab43c26dbe897790c63532e 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 35c1e2b8df1c3e009304a130c45f2a4fcbbf8d9d..974593cc7ccbc78e2be3b8dfdc50c6869eaa9ede 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 ee01ba42a9ee68975a27cbbd91314f0f0ee00c20..1f95a2fa1f3b30119598cb04a8d8df11b35d1f02 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) {