2

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

#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永远不会返回?

4

1 回答 1

2

我猜错误是在使用pthread_sigmask. 使用SIG_BLOCKandSIG_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.

您很可能会在这里这里找到答案。

特别是:

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

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

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

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

于 2016-02-02T08:37:33.287 回答