multithreading - Posix 线程 :Signal a thread that is running in while loop

标签 multithreading unix pthreads signals posix

我有一个非常简单的线程:它向服务器发送保持事件的数据包,然后休眠。我希望我的主线程向线程发出退出信号,但每当我调用 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() 吗?

最佳答案

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

总的来说,这是一个可疑的设计。使用阻塞/信号挂起代码,根据 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 如果可以,请使用其他机制。建议。

关于multithreading - Posix 线程 :Signal a thread that is running in while loop,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17606821/

相关文章:

c++ - mem_fun 失败,pthread 和类 ptr

c - 生产者消费者同步11

java - Libgdx 异步使用 ScreenUtils 并且不停止游戏循环

multithreading - Delphi XE 中的辅助线程可以接收事件吗?

c - Unix C 管道问题

bash - 在 bash 中的 if 语句中将参数传递给函数

c - 在 Netbeans 中在哪里设置 GCC 库依赖项?

C#/异步网络和GUI之间的通信

c# - 多线程场景调用Dictionary对象的set_item方法抛出NullReferenceException

克隆命令 `script` 和 PTY 后台作业问题 : terminal messed up