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)
事实证明,通过Xcode LLDB 进行调试是罪魁祸首。如果我正常构建并运行该程序,它就可以正常工作。如果我找到原因我会更新这个答案。
正如问题中所述,我已经在 lldb 中为 SIGTERM 设置了“PASS”,所以看起来 Xcode 10.0 附带的 lldb 版本中存在一个错误,它通过创建一个新的结构来“传递”信号,设置信号编号而不是通常接收到的结构。正如我之前所说,这在 macos 10.12 附带的任何版本的 lldb 中都可以正常工作
如果有人有更好的解释,请发布答案,我将接受并奖励赏金。