Reputation: 2061
I am writing a program dealing with Linux signals. To be more specific, I want to re-install signal SIGINT in child process, only to find that it doesn't work.
Here is a simpler version of my code:
void handler(int sig){
//do something
exit(0);
}
void handler2(int sig){
//do something
exit(0);
}
int main(){
signal(SIGINT, handler);
if ((pid = fork()) == 0) {
signal(SIGINT, handler2); // re-install signal SIGINT
// do something that takes some time
printf("In child process:\n");
execve("foo", argv, environ); // foo is a executable in local dir
exit(0);
}else{
int status;
waitpid(pid, &status, 0); // block itself waiting for child procee to exit
}
return 0;
}
When shell is printing "In child process:", I press ctrl+c. I find that function handler
is executed without problem, but handler2
is never executed.
Could you help me with this bug in my code?
Update:
I want the child process to receive SIGINT signal during foo
running process, is that possible?
Upvotes: 0
Views: 471
Reputation: 15218
It is not a bug - calling execve
has replaced the running binary image. The function handler2()
(and any other function of your binary) is no longer mapped in the program memory having been replaced by the image of "foo" and therefore all signal settings are replaced to a default.
If you wish the signal handler to be active during "foo" run, you have to:
One way to do this is to create a shared library that contains the signal handler and an init
function that is defined as a constructor that registers said signal handler and force it into the "foo" memory by manipulating the environment under which you execve
foo (the environ variable) to include
LD_PRELOAD=/path/to/shared_library.so
Upvotes: 2
Reputation: 9
@gby's anwser has given comprehensive background knowlegde. I am here to give another solution without shared library.
Every time child process stops or terminates, parent process will receive SIGCHLD. You can handler this SIGCHLD signal to know if child process was terminated by SIGINT. In your handler:
pid_t pid = waitpid(pid_t pid,int * status,int options)
You can get status of child process through waitpid function.
if(WIFSIGNALED(status) && (pid == child_pid)){
if(WTERMSIG(status) == SIGINT){
// now you know your foo has received SIGINT.
// do whatever you like.
}
}
Upvotes: 0