带有`SA_SIGINFO`的macOS`sigaction()`处理程序不包含`si_pid`

Bra*_*red 5 c macos signals sigaction

我正在尝试编写一个信号处理程序,它需要知道发送信号的进程的pid.从siginfo_t使用Xcode 10的macOS 10.14传递到我的处理程序中获得任何有用的东西,我没有运气.

我将代码缩减到以下最小样本以证明问题.在这个示例中,我生成了一个子进程来发送我想要测试的信号,该信号是默认的SIGTERM,但没有其他信号我尝试过更好.

假设你想在mac上构建和测试它,你可能想告诉lldb在接收信号时不要停止.你可以使用这个lldb命令:pro hand -p true -s false SIGTERM.

我也在编译C++,但我相信我已经删除了所有这些,示例代码现在应该是纯C.

请注意,如果信号源自子进程,终端或其他进程,则结果始终始终si_pid为0(以及除si_signo和之外的所有内容si_addr)无关紧要.我发送信号的次数无关紧要,因此它似乎不仅仅是竞争条件.

如何获得在macOS 10.14上发送信号的过程的pid?我不记得在10.12这个问题,这是我之前使用的.

这只是解决问题的一个示例,因此请忽略任何实际上不会导致问题的内容.

如果代码看起来应该像我期望的那样工作,那么我将有兴趣看到它所运行的系统的评论.

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

volatile sig_atomic_t histogram[3] = {0,0,0};
volatile sig_atomic_t signaled = 0;
const int testsig = SIGTERM;

void sigaction_handler(int sig, siginfo_t* info, void* context)
{
    switch (info->si_pid) {
        case 0:
        case 1:
            histogram[info->si_pid]++;
            break;

        default:
            histogram[2]++;
            break;
    }
    signaled = 1;
}

int main(int argc, const char * argv[]) {

    pid_t mainpid = getpid();
    pid_t pid = fork();
    if (pid == 0) {
        while (kill(mainpid, 0) == 0) {
            sleep(1);
            kill(mainpid, testsig);
        }
        _exit(0);
    }

    struct sigaction sigAction;
    memset( &sigAction, 0, sizeof( sigAction ) );

    sigAction.sa_sigaction = sigaction_handler;
    sigemptyset (&sigAction.sa_mask);
    sigAction.sa_flags = SA_SIGINFO;
    sigaction(testsig, &sigAction, NULL);

    while (1) {
        if (signaled) {
            printf("pid 0: %d, pid 1: %d, others: %d\n", histogram[0], histogram[1], histogram[2]);
            signaled = 0;
        }
        sleep(1);
    }
}
Run Code Online (Sandbox Code Playgroud)

Bra*_*red 2

事实证明,通过Xcode LLDB 进行调试是罪魁祸首。如果我正常构建并运行该程序,它就可以正常工作。如果我找到原因我会更新这个答案。

正如问题中所述,我已经在 lldb 中为 SIGTERM 设置了“PASS”,所以看起来 Xcode 10.0 附带的 lldb 版本中存在一个错误,它通过创建一个新的结构来“传递”信号,设置信号编号而不是通常接收到的结构。正如我之前所说,这在 macos 10.12 附带的任何版本的 lldb 中都可以正常工作

如果有人有更好的解释,请发布答案,我将接受并奖励赏金。