带有SA_SIGINFO的macOS的sigaction()处理程序不包括si_pid [英] macOS `sigaction()` handler with `SA_SIGINFO` does not include `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屋!