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

pthread_kill()发送SIGALRM导致程序终止问题求助

问题分析与解决方案

问题根源

核心问题是线程创建后,主线程发送SIGALRM的时机早于子线程完成信号处理函数的注册。SIGALRM的默认处理动作是终止整个进程,当子线程还没来得及调用sigaction设置自定义处理函数时,信号会触发默认行为,直接终止程序。而添加sleep(1)只是靠延迟给了子线程完成注册的时间,这种依赖时间的同步方式完全不可靠——不同环境下线程启动、执行的速度不同,很容易在其他场景下复现问题。

可靠的解决方案:用线程同步机制替代sleep

方案1:使用条件变量+互斥锁

通过同步机制让主线程等待,直到子线程明确告知已完成信号处理函数的注册:

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

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
int handler_registered = 0;

void obsluga(int sig) {
    printf("子线程捕获到SIGALRM信号\n");
}

void* funkcja_watku(){
    struct sigaction new_action = {.sa_handler = obsluga};
    // 注册信号处理函数
    if (sigaction(SIGALRM, &new_action, NULL) == -1) {
        perror("sigaction失败");
        pthread_exit(NULL);
    }

    // 通知主线程:已完成注册
    pthread_mutex_lock(&mutex);
    handler_registered = 1;
    pthread_cond_signal(&cond);
    pthread_mutex_unlock(&mutex);

    // 等待信号,无需sleep
    pause(); // 暂停线程直到收到信号
    return NULL;
}

int main(int argc, const char * argv[]) {
    pthread_t watek_id;
    
    if(pthread_create(&watek_id, NULL, &funkcja_watku, NULL)) {
        perror("Watek nie zostal utworzony");
        return 1;
    }
    
    // 等待子线程完成信号处理函数注册
    pthread_mutex_lock(&mutex);
    while (!handler_registered) {
        pthread_cond_wait(&cond, &mutex);
    }
    pthread_mutex_unlock(&mutex);
    
    // 此时发送信号,子线程已准备好
    if(pthread_kill(watek_id, SIGALRM)) {
        perror("Sygnal nie zostal wyslany");
        return 1;
    }
    
    if(pthread_join(watek_id, NULL)) {
        perror("Watek nie zostal usuniety");
        return 1;
    }
  
    return 0;
}

方案2:使用线程屏障(pthread_barrier)

如果只需要简单的同步点,线程屏障更简洁:

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

pthread_barrier_t barrier;

void obsluga(int sig) {
    printf("子线程捕获到SIGALRM信号\n");
}

void* funkcja_watku(){
    struct sigaction new_action = {.sa_handler = obsluga};
    if (sigaction(SIGALRM, &new_action, NULL) == -1) {
        perror("sigaction失败");
        pthread_exit(NULL);
    }

    // 等待主线程到达同步点
    pthread_barrier_wait(&barrier);

    pause();
    return NULL;
}

int main(int argc, const char * argv[]) {
    // 初始化屏障,等待2个线程(主线程+子线程)
    pthread_barrier_init(&barrier, NULL, 2);
    
    pthread_t watek_id;
    if(pthread_create(&watek_id, NULL, &funkcja_watku, NULL)) {
        perror("Watek nie zostal utworzony");
        return 1;
    }
    
    // 等待子线程完成注册
    pthread_barrier_wait(&barrier);
    
    if(pthread_kill(watek_id, SIGALRM)) {
        perror("Sygnal nie zostal wyslany");
        return 1;
    }
    
    if(pthread_join(watek_id, NULL)) {
        perror("Watek nie zostal usuniety");
        return 1;
    }

    pthread_barrier_destroy(&barrier);
    return 0;
}

额外注意事项

  • 信号处理函数obsluga要符合信号安全要求:不能调用非线程安全、非信号安全的函数(比如printf其实不是严格信号安全的,实际生产环境建议用write替代)。
  • 子线程里的sleep(2)可以替换为pause(),更高效——pause()会一直阻塞直到收到信号,避免不必要的延迟。

内容的提问来源于stack exchange,提问作者Єгорій

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 15:31:42