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

/bin/sh脚本中trap命令经C++ execvp启动后无法触发的问题

问题解决:execvp启动shell脚本后trap无法触发信号处理

问题原因

  1. 信号掩码继承:fork创建的子进程会继承调用线程的信号掩码。如果C++程序的线程(调用fork_process的线程)屏蔽了SIGTERM信号,启动的shell脚本进程会继承这个屏蔽规则,导致trap无法捕获SIGTERM。
  2. C++代码存在语法错误:pid变量未声明、char *args[]={"./test.sh",NULL}末尾缺少分号,这些错误会导致编译失败或程序行为异常。

解决方案

1. 在子进程exec前重置信号掩码

在调用execvp之前,清空子进程的信号掩码,确保所有信号(包括SIGTERM)处于未屏蔽状态。

2. 修正C++代码语法错误

补全变量声明和语句结束符,保证代码正常编译运行。

修改后的C++代码示例

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string>
#include <signal.h>

pid_t fork_process(pid_t &new_pid, const std::string& process_start) {
    int ws;
    int status;
    pid_t pid; // 补全pid变量声明

    printf("Parent: %d\n", getpid());
    char *args[]={"./test.sh", NULL}; // 添加分号
    pid = fork();
    if (pid == 0) {
        printf("Child %d\n", getpid());
        
        // 重置信号掩码,确保所有信号未被屏蔽
        sigset_t sigset;
        sigemptyset(&sigset);
        sigprocmask(SIG_SETMASK, &sigset, NULL);
        
        int r = execvp(args[0], args);
        if (r < 0) {
            const int err = errno;
            printf("exec failed with errno: %d", err);
            exit(err);
        }
    }
    new_pid = pid;
    ws = waitpid(pid, &status, WNOHANG);
    printf("%d\n", ws);
    return ws;
}

额外说明

  • 如果C++程序中存在线程使用pthread_sigmask屏蔽信号的情况,需确保调用fork_process的线程没有屏蔽SIGTERM,或者在子进程中显式解除屏蔽。
  • 单独运行脚本正常是因为直接启动时,shell进程继承的是父shell的信号掩码,而默认情况下父shell不会屏蔽SIGTERM。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 11:57:47