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
XcodeLLDB 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.