I have a problem when trying to handle a SIGUSR1 signal sent from a father process to all of his child's process. The handler on the child's does nothing. I checked for the result of the kill command and it returns 0 meaning that the message sent was ok . Can anyone help with this? Below is the code of the child process. I use execl to differ the childs code from the father. Note that the handler works well for alarm calls
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
#include <string.h>
/*Global declerations*/
int alarmflag=0;
double result=0;
int fd[2];
/*Handler for the alarm and SIGUSR1 signal*/
void signal_handler (int sig)
{
printf("******************");
if(sig==SIGALRM)
{
printf("Im child with pid:%d im going to die my value is %lf \n",getpid(),result);
alarmflag=1;
}
if(sig==SIGUSR1)
{
printf("gotit!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n");
}
}
double p_calculation ()
{
int i=2;
result=3;
double prosimo=-1;
while(!alarmflag)
{
prosimo=prosimo*(-1);
result=result+(prosimo*(4/((double)i*((double)i+1)*((double)i+2))));
i=i+2;
}
}
main(int argc,char *argv[])
{
int fd[2];
/*handling signals*/
signal(SIGALRM,signal_handler);
signal(SIGUSR1,signal_handler);
/*Notify for execution time*/
printf("PID : %d with PPID : %d executing for %d seconds \n",getpid(),getppid(),atoi(argv[1]));
/*end this after the value passed as argument*/
alarm(atoi(argv[1]));
p_calculation();
/*Notify for finish*/
printf("Done!!!\n");
}
The code for the father follows :
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
#include <sys/types.h>
pid_t *childs; //array for storing childs pids
int number_of_childs;//variable for the number of childs
int count_controls=0;
/*Handler for the SIGINT signal*/
void control_handler(int sig)
{
int j;
for (j=0;j<number_of_childs;j++)
{
kill(childs[j],SIGUSR1);
}
}
main (int argc,char *argv[]){
int i,child_status;
int fd[2];
char cast[512];
int pid;
number_of_childs=atoi(argv[1]);
signal(SIGINT,control_handler);
childs=malloc(number_of_childs*sizeof (pid_t));
if(pipe(fd)==-1)
{
perror("pipe");exit(1);
}
for (i=0;i<number_of_childs;i++){
pid=fork();
/*Create pipes to communicate with all children*/
/*Fathers code goes here*/
if(pid!=0)
{
printf("Parent process: PID= %d,PPID=%d, CPID=%d \n",getpid(),getppid(),pid);
childs[i]=pid; // Keep all your childs in an array
printf("Child:%d\n",childs[i]);
}
/*If you are a child*/
else
{
/*Change the code for the childs and set the time of execution*/
sprintf(cast,"%d",i+1);
execl("./Child.out","",cast,NULL);
}
}
/*Father should never terminate*/
while (1);
}
I cant see a problem with a child when I kill it from shell:
test]$ ./a.out 120
PID : 7406 with PPID : 7035 executing for 120 seconds
******************gotit!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
******************Im child with pid:7406 im going to die my value is -nan
Done!!!
and parent being killed with INT does kill children with USR1:
test]$ ./a.out 1 30
Parent process: PID= 7490,PPID=7035, CPID=7491
Child:7491
PID : 7491 with PPID : 7490 executing for 40 seconds
******************gotit!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
My problem is when i use control -c to the father process. It gets the
interrupt but the message from the handler that the child got the
message does not appear – Giannos 9 mins ago
The problem is that you get SIGINT in your child process.
Try to add a handler for SIGINT in the child, then run your test.
You can see what happens with your current implementation after you pressed ctrl-c:
serge 7685 7035 99 08:01 pts/3 00:00:08 ./a.out 1
serge 7686 7685 30 08:01 pts/3 00:00:02 [Child.out] <defunct>
Your child process got SIGINT and terminated. Also, it is necessary to handle the SIGCLD in the parent to get rid of all your children processes in a defunct state:
if (sig == SIGCLD)
{
// harvest terminated DEFUNCT child process
pid = waitpid(-1, &status, WNOHANG);
}
Related
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
static void sigusr(int iSig) //SIGUSER are the user defined signals
{
if (iSig == SIGUSR1)
{
printf("Received SIGUSR1 signal, going to sleep for 2 seconds\n");
sleep(2);
}
}
int main ()
{
int pid;
signal(SIGUSR1, sigusr);
pid = fork();
if (pid > 0) //Parent process created
{
for(int i=0; i<=1000;i++)
{
printf("%d\n",i);
usleep(70);
}
}
else //Child process created
{
sleep(5);
kill(pid,SIGUSR1);
exit(0);
}
}
Create 2 processes, a parent and a child using fork().
The parent prints the value of ‘i’ from 0 to 1000 and then exits.
Meanwhile the child process sleeps for 5 seconds after it is created,
sends a SIGUSR1 signal to the parent and then exits.
The parent should catch that signal, print on standard output “Received SIGUSR1 signal,
going to sleep for 2 seconds”, sleep for two seconds and then continueprinting the numbers.
But i am unable to continue the process after child process termination.
For me everything works fine if I increase usleep time, without it parent process terminates before child process send signal.
The problem is with kill call, else statement is executed only in child process, so it means that pid value is 0, kill with pid 0 sends signal to whole group, in this case to parent and a child, you should change it to
kill(getppid(), SIGUSR1);
In addition to the #complikator 's answer, you shoudl print and sleep outside the signal handler.
There are remaining questions like "main finishes before the signal is received", but this is really depending on you use case...
would look like this:
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/wait.h>
volatile static bool called = false;
static void sigusr(int iSig)
{
called = true;
}
void check_signaled(void) {
if (called) {
called = false;
printf("Received SIGUSR1 signal, going to sleep for 2 seconds\n");
sleep(2);
}
}
int main(void)
{
int pid;
pid = fork();
if (pid > 0) //Parent process created
{
signal(SIGUSR1, sigusr);
for(int i=0; i<=1000;i++)
{
check_signaled(); /* if signal come while iterating */
printf("%d\n",i);
usleep(70);
}
wait(NULL); /* wait child completion */
check_signaled(); /* signal may happen "too late" */
}
else //Child process created
{
sleep(1);
kill(getppid(),SIGUSR1);
}
}
I can kill a child process by the parent process. But what happen if a parent process has more than one child processes?
For example in below code , there are one parent process and 6 child processes. How to kill the other six child processes immediately after the parent process termination?
If you run this code, parent is terminated after 5 seconds.After that child process are terminated after another 5 seconds(totally 10 seconds).
But I want to kill 6 child processes immediately after the parent process termination.So parent and 6 child process should be terminated after 5 seconds.
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <unistd.h>
int main()
{
for(int i=0;i<6;i++) // loop will run 6 times(there are 6 child processes.)
{
if(fork() == 0)
{
printf("Started [son] pid %d from [parent] pid %d\n",getpid(),getppid());
sleep(10); //child waits 10 seconds,then it exitted.
printf("Exitted [son] pid %d from [parent] pid %d\n",getpid(),getppid());
exit(0);
}
}
//parent
sleep(5); //parent will wait 5 seconds than it will exit
printf("Parent terminated\n");
exit(0); //parent terminated.(how can I exit the the other 6 child processes too?)
}
Here's a probably more portable solution.
The fork(2) system call will return the PID of your child processes, you can store the PIDs, and then you can use kill(2) to send signal to the children and terminates them.
Notice that SIGKILL and SIGTERM signal may require some privileges of the parent process. If it doesn't have such privileges, you can send a SIGCONT to the child process, and modify the SIGCONT signal handler in your child process.
!!! Warning sign
From a signal handler using exit() is not safe. I've just checked the manual man 7 signal and found that it is not async safe. You can use _exit, _Exit or abort
Some pseudo code:
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
void* handler(int sig){
_exit(0);
}
int main()
{
pid_t children[6];
for(int i=0;i<6;i++) // loop will run 6 times(there are 6 child processes.)
{
if((children[i] = fork()) == 0)
{
signal(SIGCONT,handler);
printf("Started [son] pid %d from [parent] pid %d\n",getpid(),getppid());
sleep(10); //child waits 10 seconds,then it exitted.
printf("Exitted [son] pid %d from [parent] pid %d\n",getpid(),getppid());
exit(0);
}
}
//parent
sleep(5); //parent will wait 5 seconds than it will exit
for(int i=0;i<6;i++)
kill(children[I],SIGCONT);
printf("Parent terminated\n");
exit(0); //parent terminated.(how can I exit the the other 6 child processes too?)
}
On Linux, you can use prctl to request to be informed about the death of your parent by means of a signal (error-checking skipped).
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/prctl.h> //<<<<<<<<
#include <signal.h> //<<<<<<<<
int main()
{
for(int i=0;i<6;i++) // loop will run 6 times(there are 6 child processes.)
{
if(fork() == 0)
{
prctl(PR_SET_PDEATHSIG, SIGTERM); //<<<<<<
printf("Started [son] pid %d from [parent] pid %d\n",getpid(),getppid());
sleep(2);
printf("Exitted [son] pid %d from [parent] pid %d\n",getpid(),getppid());
exit(0);
}
}
//parent
sleep(1);
printf("Parent terminated\n");
exit(0);
//<<< Linux auto-sends the deathsignal to all children
}
For a POSIX-compliant solution that doesn't require the parent process to explicitly kill its children when it dies, you can use async-IO pipes.
Async-IO relies on signals being sent on filedescriptor events. In this case you can get notified of a close-event caused by the kernel autoclosing the filedescriptors of a dying process just as long as you make sure the autoclose closes the last reference to the pipe-end file (error-checking skipped):
#define _GNU_SOURCE
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <fcntl.h>
#include <sys/ioctl.h>
int main()
{
int pipes[6][2];
for(int i=0;i<6;i++) // loop will run 6 times(there are 6 child processes.)
{
pipe(pipes[i]); //create a pipe
if(fork() == 0)
{
//get notified on an event on the read-end (we're aiming for the EOF event)
fcntl(pipes[i][0],F_SETOWN,getpid());
ioctl(pipes[i][0], FIOASYNC, &(int){1});
for(int j=0; j<=i; j++) close(pipes[j][1]); //close all write-end ends so the refcount is 1 and the parent has the last ref
printf("Started [son] pid %d from [parent] pid %d\n",getpid(),getppid());
sleep(2);
printf("Exitted [son] pid %d from [parent] pid %d\n",getpid(),getppid());
exit(0);
}
}
//parent
sleep(1);
printf("Parent terminated\n");
exit(0);
//<<<this closes all the last write ends of the pipes and so the children will get notified with a signal
//the signal is SIGIO by default, whose default disposition is to kill the process (this can be changed by fcntl(fd,F_SETSIG,TheSignal))
}
In c++ create chain of n processes with n as input and the output of processes should be as parent1->child1(parent2)-->child2(parent3),by using recursive function im able to generate the output but unable to exit the loop i also need help in sending an input of n for which the loop should break.
below is my code:
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
int foo(const char *whoami) {
printf("I am a %s. My pid is:%d my ppid is %d\n", whoami, getpid(), getppid() );
return 1;
}
int func() {
pid_t pid=fork();
if (pid==0) { /* only execute this if child */
foo("child");
pid_t pid=fork();
if (pid==0) { /* only execute this if child */
foo("child");
func();
exit(0);
}
}
exit(0);
}
wait(0); /* only the parent waits */
return 0;
}
int main(void){
foo("parent");
func();
return 0;
}
You can't exit the loop for a simple reason, and that is, you spawn child processes endless. Whenever you fork() a new process starts, then it forks again.
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
int n=5;
int foo(const char *whoami) {
printf("I am a %s. My pid is:%d my ppid is %d\n", whoami, getpid(), getppid() );
return 1;
}
int func(int n)
{
if (n == 0)
{
return 0;
}
int pid = fork();
if (pid == -1) {
exit(0);
}
if (pid==0) {
foo("child");
n = n-1;
func(n);
exit(0);
}
else {
wait(NULL);
}
return 0;
}
int main()
{
func(n);
return 0;
}
gcc -std=c99 prog.c -o prog
./prog
OUTPUT:
I am a child. My pid is: 1159 my ppid is 1158
I am a child. My pid is: 1160 my ppid is 1159
I am a child. My pid is: 1161 my ppid is 1160
I am a child. My pid is: 1162 my ppid is 1161
I am a child. My pid is: 1163 my ppid is 1162
From what you are saying i understand you are having the following problems:
1st. You are trying to send 'data' from one process to another
2nd. You are trying to find a way to stop your program from running.
Now for the first. If you want to do that and i understood it correctly, there are 2 ways to achieve that. One is the use of shared memory and the other is the use of pipelines. Shared memory is pretty obvious on what is doing. Pipes are taking the stdout of a process and redirecting it as a stdin in the next process.
Now you need a closure to your program. A child process is executed when it executes a command(exec) or when it is told so(with an IF statement for example and a return). You can create a statement of your liking, and when a child process meets your requirments then you can make it die(There is also a way to kill the parent process from the child process with the kill(pid, SIGKILL); command.
I didn't provide you with any code because it is unclear to me the exact nature of your problem.
Hope my assuming led you to something!
I am working on some code to create a process that goes blocked and then ends, I have to be able to see the blocked state with ps.
I tried with this, but my C knowledge is not good. The code doesn't print anything.
Here it is:
#include <stdio.h>
#include <stdlib.h> //exit();
#include <unistd.h> //sleep();
int main(int argc, char *argv[]) {
createblocked();
}
int pid;
int i;
int estado;
void createblocked() {
pid = fork();
switch( pid ) {
case -1: // pid -1 error ocurred
perror("error\n");
break;
case 0: // pid 0 means its the child process
sleep(); // we put the child to sleep so the parent will be blocked.
printf("child sleeping...");
break;
default: // !=0 parent process
// wait function puts parent to wait for the child
// the child is sleeping so the parent will be blocked
wait( estado );
printf("parent waiting...\n");
printf("Child terminated.\n");
break;
}
exit(0);
}
It should be easy because its only a little program that goes blocked, but I am walking in circles I think. Any advice?
sleep() takes a parameter: the number of seconds to sleep. When you omit it, it tends to return immediately.
Also wait() takes an int *, not an int.
try this:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(int argc, char *argv[]) {
createblocked();
}
int pid;
int i;
int estado;
void createblocked() {
pid = fork();
switch(pid)
{
case -1: // pid -1 error ocurred
perror("error\n");
break;
case 0: // pid 0 means its the child process
printf("child sleeping...\n");
sleep(500); // we put the child to sleep so the parent will be blocked.
break;
default: // !=0 parent process
// wait function puts parent to wait for the child
// thechild is sleeping so the parent will be blocked
printf("parent waiting...\n");
wait(&estado);
printf("Child terminated.\n");
break;
}
exit(0);
}
note: I also moved the printf("parent waiting...\n") above the call to wait(), so you should see it before the parent blocks waiting on the child.
edit: Also, include <unistd.h>. While not strictly required in order for the program to work (on most systems), doing so will give you better compile-time error reporting for things like missing and/or incorrectly-typed function arguments.
man sleep
man wait
You should give the number of seconds as an argument in sleep().
For wait and sleep include <unistd.h>
I'm having trouble with a process forking exercise. I want to fork a child process and have it hang after announcing it has been forked, and wait for a signal to terminate, after which the parent process must announce it is terminating and then exit.
I can get the processes forked and have the parent wait for the hanging child to be killed by the signal, but it seems to kill the parent as well. I tried killing the child process specifically by its PID, but with no success.
Thanks for any help!
Code:
#include <stdio.h>
#include <signal.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <sys/types.h>
void catchInt (int signum)
{
printf("\nMy sincerest apologies, master\n");
/*kill(0, SIGINT);*/
exit(0);
}
void ignoreInt (int signum)
{
wait(NULL);
}
int main () {
pid_t pid;
/* fork process */
pid = fork();
if (pid < 0) /* error handler */
{
fprintf(stderr, "Fork Failed");
exit(-1);
}
else if (pid == 0) /* child */
{
printf("Child reporting in\n");
signal(SIGINT, catchInt);
for ( ;; )
pause();
}
else /* parent */
{
/* parent will wait for the child to complete */
signal(SIGINT, ignoreInt);
wait(NULL);
printf("You're welcome\n");
exit(0);
}
}
Even assuming you fix the code so it compiles (you've not defined tempPID), there are problems:
You set the child to go to sleep until a signal arrives.
You set the parent to wait until the child dies.
So, you have a state where neither process is going to do anything more.
You probably need the parent to send a signal to the child:
kill(pid, SIGINT);
It is not clear that you need the parent to set a signal handler.
You probably want the child to set a signal handler.
You probably don't want the infinite loop in the child.
Oh, and void main() is incorrect - int main() or int main(void) or int main(int argc, char **argv) are the approved declarations for main().
And it is tidier if you return a value (0) from main(). The C99 standard does permit you to drop off the end of main() and will treat that as returning zero, but only if the function is properly declared as returning an int.
The header for wait() and relatives in POSIX is <sys/wait.h>.
And, because I'm a sucker, here's code that compiles and might even do what you want:
#include <stdio.h>
#include <signal.h>
#include <unistd.h> /* getpid() */
#include <stdlib.h>
#include <sys/wait.h>
void catchInt(int signum)
{
printf("Child's PID is %d\n", (int)getpid());
printf("My sincerest apologies, master\n");
exit(1);
}
int main()
{
pid_t pid = fork();
if (pid < 0) /* error handler */
{
fprintf(stderr, "Fork Failed");
exit(-1);
}
else if (pid == 0) /* child */
{
printf("Child reporting in\n");
signal(SIGINT, catchInt);
pause();
}
else /* parent */
{
sleep(1);
kill(pid, SIGINT);
wait(NULL);
printf("You're welcome\n");
}
return(0);
}
Just figured out what I was doing wrong, I should have realized SIGINT is sent to every process, and so the parent was simply being sent an unhandled SIGINT, causing it to exit. Thanks for all the help (my apologies on the sloppy coding, I really shouldn't wait until the program is completed to clean that up), the code's been edited above and works as intended.
Thanks again.