I am figuring how signals work in C. Here is one of the examples taken from old exams:
#include<signal.h>
#include<unistd.h>
#include<stdio.h>
#include<errno.h>
//#include <sys/types.h>
void handler1(int sig) {
printf("Phantom");
exit(0);
}
int main()
{
pid_t pid1;
signal(SIGUSR1, handler1); //installing signal handler
if((pid1 = fork()) == 0) { //forking
printf("Ghost");
exit(0);
}
kill(pid1, SIGUSR1);
printf("Ninja");
return 0;
}
So far, GCC gives me two answers Ghost Ninja
& Ninja Phantom
. Could it produce Ghost Phantom Ninja
or any other combination made of 3 names ?
One way I see it could possibly produce 3 names is:
Fork, run in Child, print Ghost
, exit(0) => in Parent, accept/process signal and from signal Handler print Phantom
, kill child, print Ninja
. But I am not sure if my "theory" holds the ground.
Also, would the kill(pid1, SIGUSR1)
invoke handler()
?
Thanks !
A signal is a software generated interrupt that is sent to a process by the OS because of when user press ctrl-c or another process tell something to this process. There are fix set of signals that can be sent to a process. signal are identified by integers.
24 Signal HandlingA signal is a software interrupt delivered to a process. The operating system uses signals to report exceptional situations to an executing program. Some signals report errors such as references to invalid memory addresses; others report asynchronous events, such as disconnection of a phone line.
A signal handler is just a function that you compile together with the rest of the program. Instead of directly invoking the function, you use signal or sigaction to tell the operating system to call it when a signal arrives. This is known as establishing the handler. See Specifying Signal Actions.
signal returns the previous value of func that's associated with the given signal. For example, if the previous value of func was SIG_IGN , the return value is also SIG_IGN .
Let's examine this line-by line. Set up a signal handler, then fork. The child prints "Ghost" and exits. The parent makes the child print "Phantom" and exit. Then the parent prints "Ninja".
So you've really got a race condition. If the parent fires its SIGUSR1
before the child prints "Ghost", then you'll get Phantom Ninja
, or perhaps Ninja Phantom
(does kill block?)
But, if you can't get the signal off in time, then you'll get Ghost Ninja
as the child finishes before the parent signals. I don't think the reverse is possible.
Now it is conceivable that the signal could be exactly on time to hit between the printf
and the exit
, in which case Ghost
would finish, followed by Phantom
then Ninja
- or the reverse again, I think.
It's really finicky and sensitive to OS timing.
@Everyone - not tested! Feel free to contradict me, but I'll be as interested to know why as the OP.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With