为什么在辅助线程中 pause(2) 不是 return?

Why does pause(2) not return in secondary thread?

考虑我设置的这个例子来说明这一点。

#define _POSIX_C_SOURCE 199506L

#include <unistd.h>
#include <stdio.h>
#include <sys/time.h>
#include <errno.h>
#include <signal.h>
#include <pthread.h>

void hand(int sig);
void *thrfn(void *arg);

int main(void)
{
    struct sigaction act;
    struct itimerval timer;
    sigset_t mask;
    pthread_t thr;

    act.sa_handler = hand;
    sigemptyset(&act.sa_mask);
    act.sa_flags = 0;
    sigaction(SIGALRM, &act, NULL);
    /* error checking omitted */

    timer.it_interval.tv_sec = 1;
    timer.it_interval.tv_usec = 500000;
    timer.it_value = timer.it_interval;
    /* ultimately I want to build a loop; hence repeating */
    setitimer(ITIMER_REAL, &timer, NULL);

    sigemptyset(&mask);
    pthread_sigmask(SIG_SETMASK, &mask, NULL);
    /* why doesn't this prevent SIGALRM from interrupting main? */
    pthread_create(&thr, NULL, thrfn, NULL);

    puts("Main thread done.");
    getchar();

    return 0;
}

void hand(int sig)
{
    (void)sig;
    write(STDOUT_FILENO, "Handler handled.\n", 17);
}

void *thrfn(void *arg)
{
    sigset_t mask;

    (void)arg;

    sigemptyset(&mask);
    sigaddset(&mask, SIGALRM);
    pthread_sigmask(SIG_SETMASK, &mask, NULL);
    /* why doesn't this make pause() return in this thread? */

    pause();
    puts("Off thread's pause returned.");
    pthread_exit(NULL);
}

这是使用 gcc 编译的输出:

Main thread done.
Handler handled.

消息之间大约间隔一秒半。

为什么我的第二个线程 pause 从来没有 returns?

我猜错误是在 pthread_sigmask 的用法上。使用 SIG_BLOCKSIG_UNBLOCK 而不是 SIG_SETMASK 程序的行为符合您的预期。

#define _POSIX_C_SOURCE 199506L

#include <unistd.h>
#include <stdio.h>
#include <sys/time.h>
#include <errno.h>
#include <signal.h>
#include <pthread.h>

void hand(int sig);
void *thrfn(void *arg);

int main(void)
{
    struct sigaction act;
    struct itimerval timer;
    sigset_t mask;
    pthread_t thr;

    act.sa_handler = hand;
    sigemptyset(&act.sa_mask);
    act.sa_flags = 0;
    sigaction(SIGALRM, &act, NULL);
    /* error checking omitted */

    timer.it_interval.tv_sec = 1;
    timer.it_interval.tv_usec = 500000;
    timer.it_value = timer.it_interval;
    /* ultimately I want to build a loop; hence repeating */
    setitimer(ITIMER_REAL, &timer, NULL);

    sigemptyset(&mask);
    sigaddset(&mask, SIGALRM);
    pthread_sigmask(SIG_BLOCK, &mask, NULL);
    /* This prevent SIGALARM interrupring the main */
    pthread_create(&thr, NULL, thrfn, NULL);

    puts("Main thread done.");
    getchar();

    return 0;
}

void hand(int sig)
{
    (void)sig;
    write(STDOUT_FILENO, "Handler handled.\n", 17);
}

void *thrfn(void *arg)
{
    sigset_t mask;

    (void)arg;

    sigemptyset(&mask);
    sigaddset(&mask, SIGALRM);
    pthread_sigmask(SIG_UNBLOCK, &mask, NULL);
    /* This make the pause() return on SIGALARM */
    pause();
    puts("Off thread's pause returned.");
    pthread_exit(NULL);
}

该程序给出以下输出:

$ ./test 
Main thread done.
Handler handled.
Off thread's pause returned.

您可能会找到答案 here and here

特别是:

sigemptyset(&mask);
pthread_sigmask(SIG_SETMASK, &mask, NULL);

您正在取消阻塞主线程中的所有信号。同时,与:

sigemptyset(&mask);
sigaddset(&mask, SIGALRM);
pthread_sigmask(SIG_SETMASK, &mask, NULL);

您仅 SIGALARM 在子线程上阻塞。这可能与您想做的相反。 请记住,使用 SIG_SETMASK 您指定了一组被阻止的信号。