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);
}
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With