You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

sigwait()在多线程程序中无响应问题技术求助

解决sigwait线程无法捕获信号的问题

看起来你的代码里有两个关键问题导致sigwait线程收不到SIGUSR1信号,咱们一步步拆解:

问题1:线程函数签名不符合pthread要求

你的信号线程函数signal_thread带了C++默认参数void *arg = nullptr,但pthread库是基于C接口的,它要求线程启动函数的签名必须是严格的void *(*)(void *)——也就是必须接受一个void*参数,不能有默认值。这个问题会导致pthread_create调用失败,信号线程根本没启动起来,自然无法处理信号。

问题2:信号掩码设置顺序错误

你是先创建信号线程,再在主线程中设置信号掩码。这会导致信号线程启动时继承的是主线程原始的信号掩码(默认不阻塞任何信号),之后你在信号线程里调用pthread_sigmask(SIG_BLOCK, &sigset, NULL)虽然会阻塞所有信号,但更合理的做法是先在主线程阻塞所有信号,再创建线程,这样线程直接继承已阻塞的掩码,避免中间出现信号漏处理的可能。

修正后的代码

#include <stdio.h>
#include <pthread.h>
#include <signal.h>
#include <unistd.h>

static void * signal_thread(void *arg) {  // 去掉默认参数,严格匹配pthread要求
    int sig = -1;
    sigset_t sigset;
    sigfillset(&sigset);
    
    // 这里可以不用重复调用pthread_sigmask,因为线程已继承主线程的阻塞掩码
    // 若要强化保障,也可保留该调用
    // pthread_sigmask(SIG_BLOCK, &sigset, NULL);
    
    while(1) {
        int s = sigwait(&sigset, &sig);
        if(s == 0)
            printf("SIG %d received!...\n", sig);
        usleep(20);
    }
}

int main() {
    sigset_t signalset;
    pthread_t thread;
    
    // 第一步:先在主线程阻塞所有信号,让后续创建的线程直接继承该掩码
    sigfillset(&signalset);
    pthread_sigmask(SIG_BLOCK, &signalset, NULL);
    
    // 第二步:创建信号处理线程,同时检查创建是否成功
    int ret = pthread_create(&thread, NULL, &signal_thread, nullptr);
    if(ret != 0) {
        printf("Failed to create thread: %d\n", ret);
        return 1;
    }
    
    while(1) {
        raise(SIGUSR1);
        usleep(200000);  // 延长睡眠时间,避免输出过于频繁
    }
    
    return 0;
}

额外说明

  • sigwait的工作逻辑是:等待当前线程已阻塞的信号,当信号到达时,它会从进程的挂起信号队列中取出该信号并返回,不会触发传统的信号处理函数。所以必须确保目标信号被线程阻塞,这也是我们先在主线程设置掩码的核心原因。
  • 编译时记得链接pthread库,例如使用命令:g++ your_code.cpp -o your_program -pthread

内容的提问来源于stack exchange,提问作者Resist

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.06 15:17:47