I have the following simple program that sets the main program's pgid and pgroup for STDIN. Then, I have a signal handler that prints the pgid of the current process and the pgid of the process from which the signal is sent. Here is my code
pid_t pid;
void handler(int signum, siginfo_t* siginfo, void* context){
printf("pgid is %d, shell_pgid is %d \n", getpgid(siginfo->si_pid), pid);
}
int main()
{
struct sigaction sa;
sa.sa_handler = handler;
sigemptyset(&sa.sa_mask);
sa.sa_flags = SA_RESTART;
sigaction(SIGINT, &sa, NULL);
pid = getpid();
setpgid(pid, pid);
tcsetpgrp(STDIN_FILENO, pid);
while(1){
}
}
However, when I press ^C, the output I get is
^Cpgid is 335, shell_pgid is 3924
Aren't they supposed to be the same since the program is running in the main program and the signal is also sent from the same source?
I think you may be a little confused about how process group IDs work.
First, I tidied up your source:
The main change is that if your handler takes three parameters, you need to use
SA_SIGINFOand specify the handler insa_sigactionnotsa_handler. Without that, your handler may be getting invalid second and third arguments.Next I fixed your handler so it printed out
si_pidas well aspid.I also put in some additional debugging.
This is what happens when I run straight from the shell:
Note that
siginfo->si_pidreports as 0 becausesi_pidis only filled in by signals sent throughkill. This means 0 is passed togetpgid()which returns thePGIDof the calling process, which is unsurprisingly the same asgetpgid(pid)returned on the previous line.Here's what happens if I kill it with
kill -SIGINTfrom another process rather than pressing^C.As you can see the last line reports the PID of the process sending the
kill.In both the above examples, the
PGIDis already equal to thePIDwhen the process is started. Why is that? Well, we launched one command from the command line, so there is one process group (only), so thePGIDis always going to be thePID.So what happens if we launch a process group where we are not the first process? Try this:
Note this one I had to kill with
kill -SIGINTbecause a^Cgoes to the process group which is (after thePGIDis changed) onlyecho. So, thePGIDon entry is15173(the PID ofecho) but gets changed to be15174(as you requested).I think it's all working as expected.
I think the problem you have is in essence in your signal handler. First, you seem to be expecting
si_pidto be filled in. Secondly, yourprintfsays you are printingpgidandshell_pgid(twoPGIDs, whereas actually you are printing thePGIDof the process issuing the kill (or if none the result ofgetpgid(0)which is thePGIDof the calling process), then the PID of process - i.e. both the wrong way round and aPIDand aPGID. And also I suspect setting up the handler wrong may give you a junk second parameter anyway.