带有SA_SIGINFO的macOS的sigaction()处理程序不包括si_pid [英] macOS `sigaction()` handler with `SA_SIGINFO` does not include `si_pid`

查看:172
本文介绍了带有SA_SIGINFO的macOS的sigaction()处理程序不包括si_pid的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试编写一个信号处理程序,该处理程序需要知道发送信号的进程的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>易失性sig_atomic_t直方图[3] = {0,0,0};易失性sig_atomic_t发出信号= 0;const int testsig = SIGTERM;void sigaction_handler(int sig,siginfo_t * info,void * context){开关(info-> si_pid){案例0:情况1:直方图[info-> si_pid] ++;休息;默认:直方图[2] ++;休息;}发出信号= 1;}int main(int argc,const char * argv []){pid_t mainpid = getpid();pid_t pid = fork();如果(pid == 0){而(kill(mainpid,0)== 0){睡眠(1);杀死(mainpid,testig);}_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);而(1){如果(已签名){printf("pid 0:%d,pid 1:%d,其他:%d \ n",直方图[0],直方图[1],直方图[2]);信号= 0;}睡眠(1);}} 

解决方案

事实证明,通过 Xcode LLDB进行调试是罪魁祸首.如果我正常构建并运行该程序,则可以正常运行.如果我知道为什么我将更新此答案.

我已经在问题中提到了在lldb中为SIGTERM设置了"PASS",所以似乎在某种程度上Xcode 10.0附带的lldb版本中存在一个错误,并且通过创建一个传递"信号新的结构并设置信号号,而不是通常会收到的结构.正如我之前所说,在macos 10.12附带的任何lldb版本中,它的确都能正常工作

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

I'm trying to write a signal handler which needs to know the pid of the process that sends the signal. I'm having no luck with getting anything useful from the siginfo_t passed into my handler on macOS 10.14 with Xcode 10.

I've reduced my code to the below minimal sample to demonstrate the issue. In this sample I spawn a child process to send the signal I want to test which is defaulted to SIGTERM, but no other signal I've tried works any better.

Assuming you want to build and test this on a mac, you probably want to tell lldb to not stop when receiving a signal. You can use this lldb command: pro hand -p true -s false SIGTERM.

I'm also compiling with C++, but I believe I have excised all of that and the sample code should be pure C now.

Note that it doesn't matter if the signal originates from a child, terminal, or another process the result is always that si_pid is always 0 (along with everything other than the si_signo and si_addr). It doesnt matter how many times I send the signal, so it seems to not be simply a race condition.

How can I get the pid of the process sending the signal on macOS 10.14? I don't recall having this issue on 10.12 which is what I was using before.

This is just a sample to demostrate the problem, so please ignore anything that isn't actually causing a problem.

If the code seems like it should work as I expect, then I would be interested in seeing comments about systems that it works on too.

#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);
    }
}

解决方案

It turns out that debugging via Xcode LLDB is the culprit. If I build and run the program normally it works fine. If I find out why I will update this answer.

I already have the "PASS" set for SIGTERM in lldb as noted in the question, so it seems like somehow there is a bug in the version of lldb shipped with Xcode 10.0 and it is "passing" the signal by creating a new struct and setting the signal number rather then the structure that would have normally been received. As I stated before this did used to work fine in whatever version of lldb shipped with macos 10.12

If somebody has a better explaination, please post an answer and I will accept and award bounty.

这篇关于带有SA_SIGINFO的macOS的sigaction()处理程序不包括si_pid的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆