In the following code, I try to send SIGINT, SIGHUP, SIGQUIT signal to child process.
void sighup(int sig);
void sigint(int sig);
void sigquit(int sig);
These are my signal handler.
the issue is signal handler never invoked.
#include<stdio.h>
#include<signal.h>
#include<stdlib.h>
#include<unistd.h>
void sighup(int sig);
void sigint(int sig);
void sigquit(int sig);
int main()
{
int pid, i, j, k;
if ((pid = fork()) < 0)
{
perror("fork");
exit(1);
}
if(pid == 0)
{
signal(SIGHUP, sighup);
signal(SIGINT, sigint);
signal(SIGQUIT, sigquit);
}
else
{
j = 0;
for (i = 1; i <= 5; i++)
{
j++;
if (i % 2 == 0)
{
printf("PARENT: sending SIGHUP Signal : %d\n", j);
kill(pid, SIGHUP);
sleep(3);
}
else
{
printf("PARENT: sending SIGINT signal : %d\n", j);
kill(pid, SIGINT);
sleep(3);
}
}
printf("Parent sending SIGQUIT\n");
kill(pid, SIGQUIT);
}
}
void sighup(int sig)
{
signal(SIGHUP, sighup);
printf("Child: I have received sighup\n");
}
void sigint(int sig)
{
signal(SIGINT, sigint);
printf("Child: I have received sighINT\n");
}
void sigquit(int sig)
{
printf("My daddy has killed me\n");
exit(0);
}
Below lines never printed on screen
Child: I have received sighup
Child: I have received sighINT
My daddy has killed me
Output
PARENT: sending SIGINT signal : 1
PARENT: sending SIGHUP Signal : 2
PARENT: sending SIGINT signal : 3
PARENT: sending SIGHUP Signal : 4
PARENT: sending SIGINT signal : 5
Parent sending SIGQUIT
You have two problems here.
First, after the child process sets up its signal handlers, it exits right away. So the parent might get to send the first signal depending on timing, but not any others.
Put the child in a pause loop to have it wait for signals.
The other problem is that it's possible that the parent might send the first signal to the child before it can set up its signal handlers. So put a short delay in the parent to allow that to happen.
if(pid == 0)
{
signal(SIGHUP, sighup);
signal(SIGINT, sigint);
signal(SIGQUIT, sigquit);
while (1) pause();
}
else
{
sleep(1);
...
Also, calling printf and exit from a signal handler are not considered safe. It's better to have the signal handlers set a global variable and have the main part of the code check for that.
int gotsig = 0;
void sighup(int sig)
{
signal(SIGHUP, sighup);
gotsig = sig;
}
void sigint(int sig)
{
signal(SIGINT, sigint);
gotsig = sig;
}
void sigquit(int sig)
{
gotsig = sig;
}
...
while (1) {
pause();
if (gotsig == SIGHUP) {
printf("Child: I have received sighup\n");
} else if (gotsig == SIGINT) {
printf("Child: I have received sighINT\n");
} else if (gotsig == SIGQUIT) {
printf("My daddy has killed me\n");
exit(0);
}
gotsig = 0;
}
#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<signal.h>
void signint(int sig);
void sighup(int sig);
void sigquit(int sig);
int gotsig;
int main()
{
int pid,i;
pid = fork();
if(pid < 0)
{
perror("fork");
exit(0);
}
if(pid == 0)
{
signal(SIGHUP,sighup);
signal(SIGINT,signint);
signal(SIGQUIT,sigquit);
pause();
while(1)
{
if(gotsig == SIGINT)
{
printf("Child : Child process recieved SIGINT signal\n");
gotsig = -1;
}else if(gotsig == SIGHUP)
{
printf("Child : Child process recieved SIGHUP signal\n");
gotsig = -1;
}else if(gotsig == SIGQUIT)
{
printf("Dady killed me....!\n");
exit(0);
}
}
}else
{
sleep(1);
for(i = 1; i <=5 ; i++)
{
if(i % 2 == 0)
{
printf("Parent : sending SIGINT signal\n");
kill(pid,SIGINT);
sleep(3);
}else
{
printf("Parent : sending SIGHUP signal\n");
kill(pid,SIGHUP);
sleep(3);
}
}
printf("Parent : sending SIGQUIT signal\n");
kill(pid,SIGQUIT);
}
}
void signint(int sig)
{
gotsig = sig;
}
void sighup(int sig)
{
gotsig = sig;
}
void sigquit(int sig)
{
gotsig = sig;
}
Above code work fine for me.
Output :
Parent : sending SIGHUP signal
Child : Child process recieved SIGHUP signal
Parent : sending SIGINT signal
Child : Child process recieved SIGINT signal
Parent : sending SIGHUP signal
Child : Child process recieved SIGHUP signal
Parent : sending SIGINT signal
Child : Child process recieved SIGINT signal
Parent : sending SIGHUP signal
Child : Child process recieved SIGHUP signal
Parent : sending SIGQUIT signal
Dady killed me....!
Related
My aim is to pause child process after its creation. Then I want to interrupt pause and I do it by a signal that I send from the parent process via kill(). The main question is where I should put pause() in this situation.
This is what I've got so far:
int main()
{
int pid;
if ((pid = fork()) < 0) //error occured
{
perror("fork");
exit(1);
}
if (pid == 0) //___Child___
{
signal(SIGHUP, sighup);
printf("Tryna work with pause():\n");
printf("Before pause:\n");
pause();
printf("After pause.\n");
for(;;) //infinite loop
;
}
else //___Parent___
{ /* pid hold id of child */
printf("\nPID=%d\n\n",pid);
printf("\nPARENT: sending SIGHUP\n\n");
kill(pid, SIGHUP);
sleep(3); //wait 3 secs
}
}
void sighup()
{
signal(SIGHUP, sighup) //reset signal;
printf("In handler...");
}
Call it in Linux terminal like main 5053 and the output is:
PID=1939
PARENT: sending SIGHUP
The only thing to change is move kill after the sleep to give child process time to run.
{
...
printf("\nPARENT: sending SIGHUP\n\n");
kill(pid, SIGHUP);
sleep(3); //wait 3 secs
...
}
Here I want to send SIGINT signal to parent while it is sleeping. I have tried it by writing following the program. In this program, I am not getting why the signal handler for SIGINT from the parent is not executing at all?
here is the code:
#include<stdio.h>
#include<signal.h>
#include<unistd.h>
#include<stdlib.h>
void sig_usr(int signo){
if(signo == SIGINT)
printf("Signal caught!");
return;
}
int main(void){
pid_t pid, ppid;
ppid = getpid();
printf("ppid = %d\n", ppid);
if((pid = fork()) == 0){
printf("killing parent...\n");
kill(ppid, SIGINT);
printf("After killing parent...\n");
}
else{
sleep(5);
printf("%d %d ",ppid, pid);
if(signal(SIGINT,sig_usr) == SIG_ERR)
printf("Signal processed ");
}
return 0;
}
Output:
The output is printing only this much content. I think parent is not executing at all.
You need to set the signal handler before SIGINT is sent to the parent process, otherwise, the handler will not be executed. Also, the parent process is being killed before it executes anything. The easy way to fix this would be to move the sleep call after the code for the parent process, and add a delay to the child process.
#include<stdio.h>
#include<signal.h>
#include<unistd.h>
#include<stdlib.h>
void sig_usr(int signo){
if(signo == SIGINT)
printf("Signal caught!");
return;
}
int main(void){
pid_t pid, ppid;
ppid = getpid();
printf("ppid = %d\n", ppid);
if((pid = fork()) == 0){
sleep(1); // Wait for parent to finish setting up
printf("killing parent...\n");
kill(ppid, SIGINT);
printf("After killing parent...\n");
}
else{
printf("%d %d ",ppid, pid);
if(signal(SIGINT,sig_usr) == SIG_ERR)
printf("Signal processed ");
sleep(5); // Wait to be killed
}
return 0;
}
When you send SIGINT signal has not been called yet.
I think you want to set signal handler before sending SIGINT:
#include<stdio.h>
#include<signal.h>
#include<unistd.h>
#include<stdlib.h>
void sig_usr(int signo){
if(signo == SIGINT)
printf("Signal caught!");
return;
}
int main(void){
pid_t pid, ppid;
ppid = getpid();
printf("ppid = %d\n", ppid);
if((pid = fork()) == 0){
sleep(1);
printf("killing parent...\n");
kill(ppid, SIGINT);
printf("After killing parent...\n");
}
else{
printf("%d %d ",ppid, pid);
if(signal(SIGINT,sig_usr) == SIG_ERR)
printf("Signal processed ");
sleep(5);
}
return 0;
}
i have a program which creates 2 child processes, so, child 1 sends SIGINT to child 2, child 2 handles SIGINT(the handler of SIGINT blocks SIGUSR1), after SIGINT, child 1 sends SIGUSR1 to child 2.
I don't know why SIGUSR1 terminates child 2. SIGUSR1 gets blocked when SIGINT is sent.
#include <signal.h>
#include <stddef.h>
#include <stdio.h>
#include <unistd.h>
sigset_t base_mask, waiting_mask;
void handler(int signum)
{
signal(SIGINT, handler);
sigemptyset (&base_mask);
sigaddset (&base_mask, SIGUSR1);
/* Block user interrupts while doing other processing. */
if(sigprocmask (SIG_BLOCK, &base_mask, NULL) != 0)
printf("cannot block\n");
else
printf("SIGUSR1 blocked\n");
if(sigismember(&base_mask, SIGUSR1))
printf("sigusr1 in mask\n");
}
int main()
{
if(fork())
{
if(fork())
{
printf("parent out\n");
}
else//child 2
{
printf("i am sib 2 with pid = %d\n", getpid());
signal(SIGINT, handler);
pause();
printf("before sleep\n");
sleep(10);
printf("after sleep\n");
/* After a while, check to see whether any signals are pending. */
sigpending (&waiting_mask);
if (sigismember (&waiting_mask, SIGUSR1))
printf("/* SIGUSR1 pending. */\n");
sleep(2);
printf("2 out\n");
}
}
else//child 1
{
printf("i am sib 1 with pid = %d\n", getpid());
sleep(2);
printf("SIGINT to %d\n", getpid() + 1);
if(kill(getpid() + 1, SIGINT))
printf("Signal cannot be sent\n");
sleep(4);
if(kill(getpid() + 1, SIGUSR1))
printf("Signal 2 cannot be sent\n");
else
printf("SIGUSR1 sent to %d\n", getpid() + 1);
sleep(4);
}
return 0;
}
output:
parent out,
i am sib 1 with pid = 2525,
i am sib 2 with pid = 2526,
SIGINT to 2526,
SIGUSR1 blocked,
sigusr1 in mask,
before sleep,
SIGUSR1 sent to 2526
The problem is: You block the signal here in the signal handler:
void handler(int signum) {
...
if(sigprocmask (SIG_BLOCK, &base_mask, NULL) != 0)
printf("cannot block\n");
else
printf("SIGUSR1 blocked\n");
if(sigismember(&base_mask, SIGUSR1))
printf("sigusr1 in mask\n");
}
But after returning from the signal handler, the blocked signals mask is restored to the value it had on entry of the handler! So, calling sigprocmask() has only effect on the blocked signals during the current handler invocation. You have to call it outside the signal handler.
The parent process forks two children, each replace SIGUSR1 and SIGUSR2 signal respectively.
The parent process replace SIGINT signal, on catching it, send SIGUSR1 and SIGUSR2 to its children respectively.
The expected output when Ctrl-C is pressed should be:
Ctrl+C is pressed。
received SIGUSR1 signal
received SIGUSR2 signal
But on Ctrl-C I've got
Ctrl+C is pressed。
I have no idea why sig_handler_1 and sig_handler_2 are not excuted.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <signal.h>
void fun_ctrl_c(int);
void sig_handler_1(int);
void sig_handler_2(int);
pid_t pid1;
pid_t pid2;
int status;
int main() {
pid1 = fork();
if (pid1 == 0) { // child 1
// avoid to be killed
(void) signal(SIGINT, SIG_IGN);
// replace SIGUSR1
(void) signal(SIGUSR1, sig_handler_1);
raise(SIGSTOP);
} else {
pid2 = fork();
if (pid2 == 0) { // child 2
// avoid to be killed
(void) signal(SIGINT, SIG_IGN);
// replace SIGUSR2
(void) signal(SIGUSR2, sig_handler_2);
raise(SIGSTOP);
} else { // parent
(void) signal(SIGINT, fun_ctrl_c);
waitpid(-1, &status, 0);
}
}
return 0;
}
void fun_ctrl_c(int)
{
printf("Ctrl+C is pressed。\n");
kill(pid1 ,SIGUSR1);
kill(pid2 ,SIGUSR2);
(void) signal(SIGINT, SIG_DFL);
}
void sig_handler_1(int)
{
printf("received SIGUSR1 signal\n");
}
void sig_handler_2(int)
{
printf("received SIGUSR2 signal\n");
}
Your problem is that you do raise(SIGSTOP); in the child processes, so they're stopped and cannot respond to signals at all.
Replace that with pause(); — the code then works.
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <unistd.h>
void fun_ctrl_c(int);
void sig_handler_1(int);
void sig_handler_2(int);
pid_t pid1;
pid_t pid2;
int main(void)
{
pid1 = fork();
if (pid1 == 0)
{
(void) signal(SIGINT, SIG_IGN);
(void) signal(SIGUSR1, sig_handler_1);
pause();
printf("PID %d exiting\n", (int)getpid());
}
else if ((pid2 = fork()) == 0)
{
(void) signal(SIGINT, SIG_IGN);
(void) signal(SIGUSR2, sig_handler_2);
pause();
printf("PID %d exiting\n", (int)getpid());
}
else
{
(void) signal(SIGINT, fun_ctrl_c);
int status;
int pid;
printf("Interrupt me!\n");
while ((pid = waitpid(-1, &status, 0)) != -1)
printf("Child %d exited with status 0x%.4X\n", pid, status);
printf("Parent %d exiting\n", (int)getpid());
}
return 0;
}
void fun_ctrl_c(int signum)
{
printf("Ctrl+C is pressed。Received SIGINT (%d) signal\n", signum);
kill(pid1, SIGUSR1);
kill(pid2, SIGUSR2);
(void) signal(SIGINT, SIG_DFL);
}
void sig_handler_1(int signum)
{
printf("received SIGUSR1 (%d) signal\n", signum);
}
void sig_handler_2(int signum)
{
printf("received SIGUSR2 (%d) signal\n", signum);
}
Sample run (I called the program sigintusr12):
$ ./sigintusr12
Interrupt me!
^CCtrl+C is pressed。Received SIGINT (2) signal
received SIGUSR2 (31) signal
received SIGUSR1 (30) signal
PID 31184 exiting
PID 31183 exiting
Child 31184 exited with status 0x0000
Child 31183 exited with status 0x0000
Parent 31182 exiting
$
Note that you're not strictly supposed to use printf() (and many other functions, especially those that might need to allocate memory) inside a signal handler. It'll work OK here, but it is not good practice. See How to avoid using printf() in a signal handler? for more information.
I'm learning the signal of inter process communication, I made the very simple test code below:
#include <stdio.h>
#include <signal.h>
#include <stdlib.h>
#include <unistd.h>
void sighup();
void sigint();
void sigquit();
int main(int argc, const char *argv[])
{
int child_pid;
if((child_pid = fork()) < 0) exit (1);
if(child_pid == 0) {
sleep(2);
signal(SIGHUP, sighup);
signal(SIGINT, sigint);
signal(SIGQUIT, sigquit);
puts("this is the end of the child process");
} else {
printf("\n Parent: sending SIGHUP signal to child\n\n");
kill(child_pid, SIGHUP);
printf("\n Parent: sending SIGINT signal to child\n\n");
kill(child_pid, SIGINT);
printf("\n Parent: sending SIGQUIT signal to child\n\n");
kill(child_pid, SIGQUIT);
}
}
void sighup() {
signal(SIGHUP, sighup);
printf("CHILD: I have received a SIGHUP\n");
}
void sigint() {
signal(SIGINT, sigint);
printf("CHILD: I have received a SIGINT\n");
}
void sigquit() {
sleep(2);
printf("CHILD: My parent process has killed me!!");
printf("CHILD: cleaning up...\n");
exit(0);
}
It seems like the child process doesn't do anything, even doesn't print the end of the process string. any idea?
Your signal handlers are not being invoked in the child because of a race condition. The parent thread sends the child thread a signal before the child calls signal() that overrides the signal handling behavior.
In this case, the child receives a SIGINT and performs its default behavior, which is to terminate. Thus the child terminates before executing the statements after sleep(2).