sending signal between two child process - c

I create two children from the parent in the main program. The first and second child executes a program (signalSender) after their creation(alongside with the pid of the other child as an argument). signalSender has signal handler and is used for sending signal between process. The pid of the second child is given as zero as argument when first child executes signalShooter. The pid of the first child is given as argument when the second child executes sigShooter.
1) I want to find the pid of the first child via signal handler after second child sends the signal to first child. I tried to save it to global variable pid_t pid2 but it does not work.
2)I also have to send signal between these two children 100 times but i dont know where to use 'for loop' and ‘wait’ signal.
The main program:
#include <sys/types.h>
#include <sys/wait.h>
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <signal.h>
int main()
{
pid_t pid1,pid2,wid;
char *my_args[5];
int aInt = 368
char str[15];
pid1 = fork();
if (pid1 < 0)
{
fprintf(stderr, ": fork failed: %s\n", strerror(errno));
exit(1);
}
if(pid1 == 0)
{
my_args[0] = "sigperf1";
my_args[1] = "0";
my_args[2] = NULL;
execv("signalSender",my_args);
fprintf(stderr,"signalSender cannot be executed...");
exit(-1);
}
pid2 = fork();
if(pid2 < 0)
{
fprintf(stderr, ": fork failed: %s\n", strerror(errno));
exit(1);
}
if(pid2 == 0)
{
sprintf(str, "%d", pid1);
my_args[0] = "sigperf1";
my_args[1] = str;
my_args[2] = NULL;
// printf("this is converted = %s\n",my_args[1]);
execv(“signalSender",my_args);
fprintf(stderr,"signalSender cannot be executed...");
exit(-1);
}
wid = wait(NULL);
}
The signalSender:
#include <sys/types.h>
#include <sys/wait.h>
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <signal.h>
#include <ctype.h>
pid_t pid2;
struct sigaction act;
void sighandler(int signum, siginfo_t *info, void *ptr)
{
printf("Received signal %d\n", signum);
printf("Signal originates from process %lu\n",
(unsigned long)info->si_pid);
pid2 = info->si_pid;
}
int main(int argc,char **argv)
{
memset(&act, 0, sizeof(act));
act.sa_sigaction = sighandler;
act.sa_flags = SA_SIGINFO;
sigaction(SIGUSR1, &act, NULL);
pid_t current, pidOther;
current = getpid();
pidOther = atol(argv[1]);
if(pidOther != 0) // we are in the second child
{
kill(pidOther,SIGUSR1); //sending signal from second child to first
}
if(pidOther == 0) // we are in the first child
{
kill(pid2,SIGUSR1);
}
return 0;
}

You have a synchronization issue here.
Both child processes start at roughly the same time. So you can't predict which one will kill the other first. If the first child runs kill first, it will pass 0 as the pid which will kill every process in the process group. Also, each child process quits immediately after calling kill, so one may exit before the other has a chance to send it a signal.
You need to introduce some type of synchronization method. A simple way to do this is to have the second process sleep briefly before calling kill to give the first process a chance to start up. Similarly, the first process should call pause, which will tell it to wait until it receives a signal.
Once you do that, then each process can call pause and kill in a loop to go back and forth.
if(pidOther != 0) // we are in the second child
{
sleep(1); // wait for first child to start
kill(pidOther,SIGUSR1); //sending signal from second child to first
for (i=0;i<5;i++) {
pause();
kill(pidOther,SIGUSR1);
}
}
if(pidOther == 0) // we are in the first child
{
pause(); // wait until we get a signal from the second child
kill(pid2,SIGUSR1);
for (i=0;i<5;i++) {
pause();
kill(pid2,SIGUSR1);
}
}

Related

Continue output after parent child termination , i am unable to perform the operation

#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);
}
}

How to stop a child process if not completed after a timeout

I have a program that starts a child (r.out), and that child has a time limit.
I want to know how to stop running r.out after passing the time limit.
I am running the code on Linux.
This is what I have so far:
#include <unistd.h>
#include <signal.h>
#include <err.h>
#include <stdio.h>
#include <stdlib.h>
#define TIME_LIMIT 1 //determine time limit
void my_function(); //supposed to include the submitted code
void alarm_handler(int);
int main()
{
if (sigaction(SIGALRM, NULL, NULL) == -1)
err(1, NULL);
signal(SIGALRM, alarm_handler); // assigning an alarm handler for SIGALRM
alarm(TIME_LIMIT); // install an alarm to be fired after TIME_LIMIT
system("./r.out"); //Running the file
alarm(0);
return 0;
}
void alarm_handler(int sig)
{
printf("%s" , "Time limit exceeded");
//Here i want a code to stop the r.out file
}
In order to kill the child, you need to know its pid. You can get it if you start the program with fork and exec instead of system.
In addition to a signal handler for SIGALRM, set up one for SIGCHLD (received when a child process finishes) as well. After calling alarm to set the timer, call pause. This function will return when you get either of the two signals.
In the signal handlers you should only set a global flag. Calling printf from within a signal handler can lead to undefined behavior.
After pause returns, check each of the two flags. If the timeout flag is set, you can terminate the child with kill.
In either case, call wait to reap the child process's pid.
#include <unistd.h>
#include <signal.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#define TIME_LIMIT 1 //determine time limit
void alarm_handler(int);
void child_handler(int);
int timeout = 0;
int child_done = 0;
int main()
{
pid_t pid = fork();
if (pid == -1) {
perror("fork failed");
exit(1);
} else if (pid == 0) {
// child process
execl("./r.out","r.out", NULL);
perror("exec failed");
_exit(1);
}
// set up the signal handlers after forking so the child doesn't inherit them
signal(SIGALRM, alarm_handler);
signal(SIGCHLD, child_handler);
alarm(TIME_LIMIT); // install an alarm to be fired after TIME_LIMIT
pause();
if (timeout) {
printf("alarm triggered\n");
int result = waitpid(pid, NULL, WNOHANG);
if (result == 0) {
// child still running, so kill it
printf("killing child\n");
kill(pid, 9);
wait(NULL);
} else {
printf("alarm triggered, but child finished normally\n");
}
} else if (child_done) {
printf("child finished normally\n");
wait(NULL);
}
return 0;
}
void child_handler(int sig)
{
child_done = 1;
}
void alarm_handler(int sig)
{
timeout = 1;
}

synchronization between two process in c

I am trying to send signals between two child in alternative way for 100 times.
Here is my snippet of code.
here is the link to the whole question:
sending signal between two child process
But i have synchronization issue in the loop.
where is the right position to put the sigsuspend()?
#include <sys/types.h>
#include <sys/wait.h>
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <signal.h>
#include <ctype.h>
pid_t pid2;
struct sigaction act;
sigset_t mask,oldmask,temp;
void sighandler(int signum, siginfo_t *info, void *ptr)
{
printf("Received signal %d\n", signum);
printf("Signal originates from process %lu\n",
(unsigned long)info->si_pid);
pid2 = info->si_pid;
}
int main(int argc,char **argv)
{
int i,j,counter = 0,counter2 = 0;
sigemptyset(&mask);
sigemptyset(&temp);
//sigemptyset(&oldmask);
sigaddset(&mask,SIGUSR1);
//sigset_t mask;
memset(&act, 0, sizeof(act));
act.sa_sigaction = sighandler;
act.sa_flags = SA_SIGINFO;
if(sigaction(SIGUSR1, &act, NULL) == -1)
fprintf(stderr, "sigaction failed: %s\n", strerror(errno));
pid_t current, pidOther;
current = getpid();
pidOther = atol(argv[1]);
int k;
for(k = 0;k < 100;k++){
if(pidOther != 0){ // second child
kill(pidOther,SIGUSR1);
sigprocmask(SIG_BLOCK,&mask,&oldmask);
counter++;
printf("2nd child = %d sent signal to 1st child = %d signal number = %d\n",getpid(),pidOther,counter);
//sigprocmask(SIG_BLOCK,&mask,&oldmask);
sigsuspend(&temp);
}
if(pidOther == 0) // fisrt child
{
//pause();
kill(pid2,SIGUSR1);
sigprocmask(SIG_BLOCK,&mask,&oldmask); // was blank
counter++;
printf("\nj=%d 1st child = %d sent signal to 2nd child = %d signal counter = %d\n",j,getpid(),pid2,counter);
printf("test1\n");
sigsuspend(&temp); // was pause()
}
}
return 0;
}
I don't see you calling fork() anywhere. Also taking the process ID of the second process is not the way your program should know about the child process. Here's a simple example of how to use fork.
pid_t pid = fork();
if (pid == 0)
{
// executes only in child process..
// do stuff related what you need to do in child process
}
else
{
// executes only in parent process
// pid variable contains the child process's PID.
// do stuff related what you need to do in parent process
}
// runs in both parent and child.
The problem is that the first time the first child loops, pid2 is 0, so it sends the signal to every process in the process group (including itself), which means it will start looping immediately, sending signals (just) back to itself...

Father process was block while set SIGCHLD

This is my code, I had simplified it.
#include <stdio.h>
#include <unistd.h>
#include <signal.h>
#include <sys/wait.h>
void signal_handle(int sig)
{
int status;
wait(&status);
}
int main()
{
pid_t pid = fork();
if (pid > 0)
signal(SIGCHLD, signal_handle);
if (pid == 0) {
if (execl("/bin/ls", "/", (char *)0) < 0)
{
perror("execl");
return -1;
}
}
return 0;
}
When I run it, I found that, son process print the run result, but father process
was blocked.
what should I do, if a father has much son process? set wait(&status) for every one?
I'm very sorry for my bad english!
I don't see why the parent process would hang, and it doesn't on my machine.
After the fork(), the parent process invokes signal() to set the signal handler and immediately exits. The child, meanwhile, executes ls to print the contents of the current directory (because the "/" argument becomes argv[0], the program name, and there are no additional arguments). It then exits too. Except under very unlikely circumstances, the parent has exited long before the child completes.
If you want the parent process to wait until it gets the 'death of a child' signal, add a call to pause() in the parent-only execution path:
#include <stdio.h>
#include <unistd.h>
#include <signal.h>
#include <sys/wait.h>
static void signal_handle(int sig)
{
int status;
pid_t pid = wait(&status);
printf("%d: signal %d child %d status 0x%.4X\n", (int)getpid(), sig, (int)pid, status);
}
int main(void)
{
pid_t pid = fork();
if (pid > 0)
{
signal(SIGCHLD, signal_handle);
pause();
}
else if (pid == 0)
{
execl("/bin/ls", "ls", "/", (char *)0);
perror("execl");
return -1;
}
else
perror("fork");
return 0;
}

waitpid() not allowing SIGINT to be sent to child process?

#include <stdio.h>
#include <string.h>
#include <strings.h>
#include <limits.h>
#include <unistd.h>
#include <stdlib.h>
#include <pwd.h>
#include <dirent.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <signal.h>
void sig_handler(int signal);
int pid, forkFlag = 0;
int main( int argc, char **argv, char **envp )
{
sigset(SIGINT, sig_handler); //handle ctrl + c
sigignore(SIGTSTP);
sigignore(SIGSTOP);
int ex, rv, status;
forkFlag = 1; //fork is being called
pid = fork();
if(pid == -1){
perror("fork");
exit(2);
}
else if (pid == 0){ //if child process
ex = access(argv[0], X_OK); //check if file is executable
if(ex){
perror("access");
exit(1);
}
else{
rv = execve(argv[0], argv, envp); //run program in child process
if(rv == -1){
perror("execve");
exit(1);
}
}
exit(0); //end child process
}
else{
rv = waitpid(pid, &status, 0); //wait for child
if(rv == -1){
perror("waitpid");
}
if(WEXITSTATUS(status)){ //check status of child if it did ot return 0
printf("The return status of the child was %d\n", WEXITSTATUS(status));
}
}
forkFlag=0;
}
void sig_handler(int signal)
{
if(signal == SIGINT && (pid && forkFlag)){
kill(pid,signal); //send kill to child
}
}
I'm trying to make my program ignore ctrl + C, except when there is a child process running, then it sends the the SIGINT to the child process. However, when I press ctrl + c when the child process is running, waitpid() returns -1 with the error "Interrupted System Call." This makes the child process stop running, but if I use ps, the child process is still there, but now labeled as defunct. I know from printf statements that kill is being calle din the function sig_handler, and that pid and forkFlag are their correct values. Is waitpid() making my program ignore the kill? How do I fix this? I know this code does next to nothing, but it's a small portion of my code (the only part involving fork)
Thanks for any help.
The problem is that the child processes get the same overridden handler for SIGINT. You probably want to reset the signal handler in the child process after the fork, or you might want to install the signal handler in the parent after you've already forked the child, so it doesn't inherit the overriden handler.

Resources