Make children process wait until receiving parent's signal
Solution 1
if (pid == 0){ //child
printf("printed from child [%d]\n", getpid());
signal(SIGUSR1, measure_time); //measure_time is a function
exit(0);
}
The children get created, set up the handler, and immediately exit (i.e. die). Make them sleep or block on something so there is actually time for the parent to deliver the signals.
Update
#define _POSIX_SOURCE
#include <stdio.h>
#include <errno.h>
#include <unistd.h>
#include <signal.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
void measure_time(int sig)
{
printf("child [%d] received signal %d\n", getpid(), sig);
}
int main(int argc, char *argv[])
{
int n_task = 4;
pid_t pid;
pid_t pid_array[n_task];
for (int i = 0; i < n_task; i++)
{
pid = fork();
if (pid < 0)
{
perror("fork");
exit(1);
}
if (pid == 0) //child
{
printf("printed from child [%d]\n", getpid());
signal(SIGUSR1, measure_time); //measure_time is a function
sleep(5);
exit(0);
}
//parent
pid_array[i] = pid;
}
//This code is executed from parent only
sleep(1);
for (int i = 0; i < n_task; i++)
kill(pid_array[i], SIGUSR1);
for (int i = 0; i < n_task; i++)
wait(NULL);
return (0);
}
All processes and threads are subject to whims of the OS scheduler. In your initial code the children and the parent can potentially terminate before the sequence of events you hope to take place can ever occurs. The children can die before the parent ever sends a signal; the parent can send its signals before the children ever set up their handler (and SIGUSR1 kill the process because that is its default in the absence of a handler). There is so little code to execute all this takes place in milliseconds, less than the time than any of these processes gets scheduled to run (and thus setting up enough to fulfill your expections). I have added some sleep
to give it all some breathing room and a wait
so the parent doesn't die. This should allow you to see how it works.
Solution 2
if (pid == 0){ //child
printf("printed from child [%d]\n", getpid());
signal(SIGUSR1, measure_time); //measure_time is a function
pause();
exit(0);
}
I think problem is, child Processes are terminated immediately after they created. so
Use pause() function to wait for the signal to arrive.
And if some child Processes won't respond as expected try this also.
for (j = 0; j < n_task; j++)
{
kill(pid_array[j], SIGUSR1);
sleep(1);
}
Zk1001
Updated on November 11, 2020Comments
-
Zk1001 over 3 years
I want to create N children from a parent. I want all the children to start (a function - to measure time) at the same time. So I put the function in a signal handler and when the parent finish creating (fork) all children, it sends the signal (using kill(children_id)) to all children to let make start. The code is below but it doesn't work as expected. Specifically, it forked all children but does not execute function "measure_time" at all. This function does not thing but record execution time and print out. Could someone let me know if I am doing something wrong?
int n_task = 4; for (i = 0; i < n_task; i++){ pid = fork(); if (pid < 0){ printf("cannot fork!\n"); } else if (pid == 0){ //child printf("printed from child [%d]\n", getpid()); signal(SIGUSR1, measure_time); //measure_time is a function exit(0); } else { pid_array[i] = pid; } } //This code is executed from parent only for (int i = 0; i < n_task; i++) { kill(pid_array[i], SIGUSR1); }
-
Jonathan Leffler over 10 yearsThe
pause()
function is the classic and simplest way to wait for a signal to arrive. It never returns normally; it only ever returns when a signal interrupts it. -
Zk1001 over 10 yearsthis is somewhat similar the Duck's answer so I will comment here. I tried this but among 4 threads created, only 1 (sometimes) 2 threads are executed. Is there still something missing?
-
Deadlock over 10 yearsfor (j = 0; j < n_task; j++) { kill(pid_array[j], SIGUSR1); sleep(1); } try this way, it'll work. ( i don't know exactly why this happen but i think it's because parent process send signal, before some child Processes install the signal handler.)
-
Deadlock over 10 yearsBut this will not help you to achieve your purpose, to start (a function - to measure time) at the same time from all the children. But all child Processes will be executed.
-
Zk1001 over 10 yearsYes it works as you thought. Great. But then, I have to delay the signal sends! This is not what I wanted. I want the send the signal, to be more accurate, broatcast, to all children and let them start at the same time, more or less. Anyone could give a hint?
-
Duck over 10 yearsAre you guys for real? Somewhat similar?
-
Zk1001 over 10 yearsTried your code. But it doesn't make all 4 tasks start at the same time. To be more specific, I added sleep(1) in measure_time(). The children print their "received signal" on a basis of 1 second. Could you give it one more try?
-
Duck over 10 yearsI edited the parent kill/wait code into 2 loops. Maybe that is what you were seeing. My apologies for being short with you. Not even finished with my morning coffee.