multipathd: fix SIGUSR2 handling
authortang.junhui <tang.junhui@zte.com.cn>
Thu, 29 Dec 2016 07:56:14 +0000 (15:56 +0800)
committerChristophe Varoqui <christophe.varoqui@opensvc.com>
Thu, 16 Mar 2017 06:43:31 +0000 (07:43 +0100)
SIGUSR2 is not blocked by default, it would cause bellow conflict
in removing of the last path:
-------------------------------------------------------------
uevent processing thread                 | waiter thread
-----------------------------------------|-------------------
uev_remove_path()                        |   waiteventloop()
  lock(&vecs->lock)                      |
  ev_remove_path()                       |
    dm_queue_if_no_path()----------------|----> dm_task_run()
    flush_map()                          |      |
      remove_map_and_stop_waiter()       |      -> pthread_cleanup_push(cleanup_lock, &waiter->vecs->lock);
        _remove_map()                    |         lock(&waiter->vecs->lock)//wait for the locker
          stop_waiter_thread()           |
            pthread_cancel(thread)       |
            pthread_kill(thread,SIGUSR2)-|------> sigusr2 (int sig)
                                         |          condlog()
                                         |          fprintf() //it has test cancel point
                                         |          cleanup_lock() //thread cancel, and pop, which unlock the
                                         |                           locker of uevent processing thread
--------------------------------------------------------------
Since SIGUSR2 is only needed when waiter thread running in dm_task_run(),
and it has already been unblocked before dm_task_run(), so this patch block
SIGUSR2 for other times.

Change-Id: I8c46292dc954415764ebbe054498b4f7ea53c1c6
Signed-off-by: tang.junhui <tang.junhui@zte.com.cn>
multipathd/main.c

index 0c69f3b..e5046a2 100644 (file)
@@ -2257,6 +2257,12 @@ sigusr2 (int sig)
 static void
 signal_init(void)
 {
+       sigset_t set;
+
+       sigemptyset(&set);
+       sigaddset(&set, SIGUSR2);
+       pthread_sigmask(SIG_SETMASK, &set, NULL);
+
        signal_set(SIGHUP, sighup);
        signal_set(SIGUSR1, sigusr1);
        signal_set(SIGUSR2, sigusr2);