在信号处理程序中使用 `pause()` 有什么缺陷?

What are the pitfalls of using `pause()` in signal handler?

我想暂停和恢复线程。列出的方法很少 here。但是我想到了使用 unistd.h.

中的 pause() 库函数

在信号处理程序中使用暂停有哪些缺陷?

我注意到的一个是,当我发送 0 暂停线程并再次发送 0 时,我的信号会排队。我需要发送 1 两次以恢复线程。

我想这样的案例可能还有很多。如果我想在信号处理程序中使用 pause()sleep() 如何处理这种情况。

#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
#include <signal.h>
#include <stdbool.h>

static bool thread_ready = false;

static void cb_sig(int signal)
{
        if (signal == SIGUSR1)
                pause();
        else if (signal == SIGUSR2)
                ;
}

static void *thread_job(void *ignore)
{
        int i = 0;
        struct sigaction act;

        sigemptyset(&act.sa_mask);
        act.sa_flags = 0;
        act.sa_handler = cb_sig;

        if (sigaction(SIGUSR1, &act, NULL) == -1)
                printf("unable to handle siguser1\n");
        if (sigaction(SIGUSR2, &act, NULL) == -1)
                printf("unable to handle siguser2\n");

        thread_ready = true;
        while (1) {
                printf("thread counter: %d\n", i++);
                sleep(1);
        }

        return NULL;
}

int main()
{
        bool running;
        int user_input;
        pthread_t thread;

        if (pthread_create(&thread, NULL, thread_job, NULL))
                return -1;

        while (!thread_ready);

        for (running = true; running; ) {
                printf("0: pause thread, 1: resume thread, -1: exit\n");
                scanf("%d", &user_input);

                switch(user_input) {
                case -1:
                        running = false;
                        break;
                case 0:
                        pthread_kill(thread, SIGUSR1);
                        break;
                case 1:
                        pthread_kill(thread, SIGUSR2);
                        break;
                }
        }

        pthread_kill(thread, SIGKILL);
        return 0;
}

信号处理程序不应该 sleep(),而且可能不应该 pause(),尽管从技术上讲,这两个函数都是 async-signal-safe。信号处理程序应该 运行 快速并最小化或(最好)完全避免阻塞。

至于具体的陷阱,您已经注意到了一个:默认情况下,信号在其处理程序为 运行ning 时会自动被阻止。可以以一种避免这种情况的方式安装处理程序,但这对您没有帮助:如果您一直发送由特定处理程序处理的信号,那么您将始终至少有一个线程在该处理程序中被阻塞。如果您一直将它们发送到同一个线程,那么该线程将永远不会解除阻塞。

更一般地说,信号掩码、信号和信号处理程序在信号接收时阻塞之间可能会发生许多不良交互。

此外,pause() 更像是 non-specific,除非您将它与设置相当严格的信号掩码结合使用(在这种情况下,sigsuspend() 可能是更好的选择)。但是,如果您设置了限制性信号掩码,那么您可能会干扰信号的其他用途。

除了避免在信号处理程序中使用 pause()sleep() 之外,不要 "handle" 此类问题。