Posix线程:表示在while循环中运行的线程

时间:2013-07-12 02:59:11

标签: multithreading unix pthreads signals posix

我有一个非常简单的线程:它将keep-alive数据包发送到服务器,然后休眠。我希望我的主线程能够通知线程退出,但每当我调用pthread_kill()时,它似乎都会导致我的进程崩溃。

我尝试在我的while循环开始时调用sigpending()后跟sigismember(),但我认为它崩溃了,因为它不知道任何处理信号的句柄(我使用的是sigaddset( )在while循环之前),如下:

void* foo(void* arg)
{
    sigset_t set, isSignal;

    sigemptyset(&set);
    if (sigaddset(&set, SIGUSR1) == -1) { /* ... */ }

    while (1) {
        if (sigpending(&isSignal) != 0) { /* .. */ }
        else if (sigismember(&isSignal, SIGUSR1)) {
            break;
        }

        sendKeepAlive();
        sleep(SECONDS);
    }
    return NULL;
}

似乎是pthread_kill(pth,SIGUSR1);使程序死亡。请问发送信号的正确方法是什么?我应该使用pthread_sigmask()吗?

2 个答案:

答案 0 :(得分:4)

当操作系统发出信号但进程或线程已阻止时,信号处于挂起状态。如果您尚未阻止SIGUSR1,那么它将被交付,SIGUSR1的默认处置是终止该进程。你的sigpending在这种情况下什么都不做;它被有效地绕过了。首先用pthread_sigmask阻止SIGUSR1或(可选)处理它。

总之,这是一个可疑的设计。使用阻塞/ sigpending代码,根据SECONDS设置的时间长短,您仍然可以等待很长时间,然后线程才会发现它是时候关闭了。如果你真的想要使用信号,我会建议建立一个设置开关的信号处理程序。当SIGUSR1被传递时,处理程序将被调用,它设置开关,sleep将被信号中断,你检查EINTR并立即循环检查开关然后pthread_exit

选项1 (在linux上编译)

#define _POSIX_C_SOURCE 2

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

void* foo(void* arg)
{
    sigset_t set, isSignal, allSigs;

    sigfillset(&allSigs);

    if (sigprocmask(SIG_SETMASK, &allSigs, NULL) == -1)
    {
        printf("sigprocmask: %m\n");
        exit(1);
    }

    sigemptyset(&set);

    if (sigaddset(&set, SIGUSR1) == -1)
    {
        printf("sigaddset: %m\n");
        exit(1);
    }

    while (1)
    {
        if (sigpending(&isSignal) != 0)
        {
            printf("sigpending: %m\n");
            exit(1);
        }
        else
            if (sigismember(&isSignal, SIGUSR1))
            {
                printf("signal pending for thread, exiting\n");
                break;
            }

        printf("Doing groovy thread stuff...\n");

        sleep(2);
    }

    return NULL;
}


int main(int argc, char *argv[])
{
    pthread_t tid;
    int rc;

    rc = pthread_create(&tid, NULL, foo, NULL);

    if (rc)
    {
        printf("pthread_create: %m\n");
        exit(1);
    }

    sleep(10);

    pthread_kill(tid, SIGUSR1);

    pthread_join(tid, NULL);

}

选项2 (在linux上编译)

#define _POSIX_C_SOURCE 2

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

volatile int stop = 0;

void handler(int sig)
{
    stop = 1;
}

void* foo(void* arg)
{
    signal(SIGUSR1, handler); //use sigaction, i'm too lazy here

    while (! stop)
    {
        printf("Doing groovy thread stuff...\n");

        if (sleep(4) > 0)
            if (errno == EINTR)
            {
                printf("sleep interrupted, exiting thread...\n");
                continue;
            }
    }

    return NULL;
}


int main(int argc, char *argv[])
{
    pthread_t tid;
    int rc;

    rc = pthread_create(&tid, NULL, foo, NULL);

    if (rc)
    {
        printf("pthread_create: %m\n");
        exit(1);
    }

    sleep(10);

    pthread_kill(tid, SIGUSR1);

    pthread_join(tid, NULL);

}

选项3 如果可以,请使用其他一些机制。宜。

答案 1 :(得分:2)

我会丢失信号,只使用pthread条件变量,例如pthread_cond_timedwait()):

... IMHO