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

时间:2019-06-20 11:51:29

标签: c pthreads signal-handling

我想暂停线程并恢复它。 here中列出了几种方法。但是我想到了使用pause()中的unistd.h库函数。

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

我注意到的一个问题是,当我发送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;
}

1 个答案:

答案 0 :(得分:6)

信号处理程序不应该sleep(),并且可能不应该pause(),即使从技术上讲,这两个函数都是异步信号安全的。信号处理程序应快速运行并最小化,或者(最好)完全避免阻塞。

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

通常,信号屏蔽,信号传递和信号处理程序在接收信号时阻塞之间可能会发生许多不良的交互作用。

此外,除非您将pause()与设置相当严格的信号掩码结合使用,否则sigsuspend()是非特定的(在这种情况下,pause()可能是一个更好的选择)。但是,如果设置限制性信号掩码,则可能会干扰信号的其他用途。

除了避免在信号处理程序中使用sleep()PrintDocument printDocument = new PrintDocument(); printDocument.PrintPage += PrintDocumentOnPrintPage; printDocument.PrinterSettings.PrinterName = "TestPrinter"; printDocument.Print(); printDocument.Dispose(); 之外,不要“处理”此类问题。