Use loop to fork varying number of children - c

Most of the examples I come across show how to fork, like this one:
main()
{
int pid;
pid = fork();
// child
if (pid == 0)
{
...
}
// Parent
else if (pID > 0)
{
...
}
}
Some show how to fork 2 children, like so
pid = fork();
// Child
if ( pid==0 )
{
...
}
// Parent
else if ( pid>0 )
{
pid=fork();
// Second child
if ( pid==0 ){
...
}
}
And here is my attempt to fork 5 children...
pid = fork();
// Child
if ( pid==0 )
{
...
}
// Parent
else if ( pid>0 )
{
pid=fork();
// Second child
if ( pid==0 ){
...
}
// Parent
else if ( pid>0 )
{
pid=fork();
// Third child
if ( pid==0 ){
...
}
// Parent
else if ( pid>0 )
{
pid=fork();
// Fourth child
if ( pid==0 ){
...
}
// Parent
else if ( pid>0 )
{
pid=fork();
// Fifth child
if ( pid==0 ){
...
}
}
}
}
}
Question:
My point is that this is insanity. Is there a cleaner way to loop through and create a varying number of children (ie. specified via a command line argument)?
NOTE:
It is vitally important that the children distinguish themselves apart (ie. write "hi, I am child number 6"...) as my job involves each process signalling a different computer. Currently I am doing so using semaphores and an array of target computers. What I would rather want is increasing indeces 1..N for the processes.

Use a for loop. Each process will get it's own copy of the loop variable.
int pid;
int numKids = 5;
int procNum;
for(procNum = 0; procNum < numKids; procNum++) {
// Note: haven't included error handling...
pid = fork();
if (pid == 0) {
break;
}
}
if (pid == 0) {
// child specific stuff. procNum is set to the "child number"
}
else {
// parent stuff
}

Related

Why can't I catch SIGCHLD every time after fork?

I am trying to create 4 child processes and until the children die, parent should wait. I wrote a program but when I run this code, 1 out of 10, it can't catch the SIGCHLD from every child and my program goes to infinite loop after. It happens really rare but still..
Could you tell me why and how can I fix it?
Here is my code.
sig_atomic_t child_exit_status;
sig_atomic_t child_numbers = 0;
void clean_up(int signal_number, siginfo_t * info, void* context)
{
//printf("SIGCHILD from %d calling\n", info->si_pid);
waitpid(info->si_pid, &child_exit_status, 0);
child_numbers++;
}
int main(int argc, char **argv)
{
// SIGCHLD catcher
struct sigaction sigchld_action;
memset(&sigchld_action, 0, sizeof(sigchld_action));
sigchld_action.sa_sigaction = &clean_up;
sigchld_action.sa_flags = SA_SIGINFO;
sigaction(SIGCHLD, &sigchld_action, NULL);
int pid1, pid2, pid3, pid4;
printf("pid : %d\n", getpid());
pid1 = fork();
//child1
if(pid1 == 0)
{
printf("child1 %d, parent %d\n", getpid(), getppid());
}
else
{
pid2 = fork();
//child2
if(pid2 == 0)
{
printf("child2 %d, parent %d\n", getpid(), getppid());
}
else
{
pid3 = fork();
//child3
if(pid3 == 0)
{
printf("child3 %d, parent %d\n", getpid(), getppid());
}
else
{
pid4 = fork();
//child4
if(pid4 == 0)
{
printf("child4 %d, parent %d\n", getpid(), getppid());
}
else
{
while(child_numbers < 4)
{
}
printf("i got the signals.");
}
}
}
}
return 0;
}
I tried something new but it also doesn't work..
void clean_up(int signal_number, siginfo_t * info, void* context)
{
printf("SIGCHILD from %d calling\n", info->si_pid);
while (1)
{
int status;
pid_t pid = waitpid(-1, &status, WNOHANG);
if (pid <= 0)
{
break;
}
else
{
waitpid(pid, &status, 0);
break;
}
}
child_numbers++;
}

Why the child process will not exit normally?

Why is the following program will not work properly?
int cnt = 0;
void deal(int sig) {
++cnt;
}
int main() {
signal(SIGUSR1, deal);
pid_t child = fork();
if (child == 0) {
ptrace(PTRACE_TRACEME, 0, NULL, NULL);
raise(SIGSTOP);
freopen("ab.out", "w", stdout);
printf("child : %d\n", cnt);
} else {
int app_status, app_sig, fd;
struct user_regs_struct app_reg;
struct rusage app_ruse;
waitpid(child, &app_status, 0);
printf("father: waitpid: %d\n", app_status);
while (1) {
ptrace(PTRACE_SYSCALL, child, NULL, NULL);
wait4(child, &app_status, 0, &app_ruse);
if (WIFEXITED(app_status)) {
printf("father: child exit normally, pid - %d\n", child);
break;
}
if (WIFSIGNALED(app_status) || (WIFSTOPPED(app_status)
&& WSTOPSIG(app_status) != SIGTRAP)) {
....
break;
}
ptrace(PTRACE_GETREGS, child, NULL, &app_reg);
if (app_reg.orig_rax == SYS_open && (fd = app_reg.rax) >= 0) {
kill(child, SIGUSR1);
}
}
}
return 0;
}
When run the program, got follow result
Why did the child process exit directly after receiving the signal?
The full code can got here.
https://pastebin.ubuntu.com/p/FddVZpfGH7/

C - child process of a child process

I have to reproduce a process family like this: father --> child --> grandson.
I don't understand why the grandson code is never executed.
My code scheme is like this:
int main() {
int fatherProcess, p1, p2;
p1 = fork();
if(p1 <0) {
perorr("Failed to create P1\n");
} else if(p1 == 0) {
//child code
p2 = fork();
if(p2 < 0) {
perorr("Failed to create P2\n");
} else if(p2 == 0) {
//grandson code
pritnf("Hello I'm the GRANDSON\n");
} else {
//child code
pritnf("Hello I'm the CHILD\n");
}
} else {
//father code
pritnf("Hello I'm the father\n");
}
return 0;
}
The stamp that I get is:
- Hello I'm the GRANDSON
- Hello I'm the father
You have made two spelling error. I have fixed it and you can try the following code:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
int main() {
int fatherProcess, p1, p2;
p1 = fork();
if(p1 <0) {
perror("Failed to create P1\n");
} else if(p1 == 0) {
//child code
p2 = fork();
if(p2 < 0) {
perror("Failed to create P2\n");
} else if(p2 == 0) {
//grandson code
printf("Hello I'm the GRANDSON\n");
} else {
//child code
printf("Hello I'm the CHILD\n");
}
} else {
//father code
printf("Hello I'm the father\n");
}
return 0;
}
Your code:
perorr --> perror
pritnf --> printf

Signal handlers not working across different process groups

I am using execp under a child created using fork for which I have set new process group and have set it has foreground process group using tcsetpgrp
Here is my code for main
int main()
{
signal(SIGINT,SIG_IGN);
signal(SIGTSTP,SIG_IGN);
pid_t pid=fork();
if(pid==-1)
{
perror("Error in forking");
}
else if(pid == 0)
{
signal(SIGTTOU, SIG_IGN);
setpgid(getpid(),getpid());
//check denotes if process needs to be run in background or not
if(!check)
{
tcsetpgrp(STDOUT_FILENO,getpgid(getpid()));
tcsetpgrp(STDIN_FILENO,getpgid(getpid()));
}
signal(SIGTSTP, tstphandler);
signal(SIGINT,inthandler);
if(strlen(token)>0)
{
execer=execlp(token,token,args,(char*)NULL);
if (execer==-1)
{
printf("Error in execution);
}
exit(0);
}
}
else
{
//processes is a data structure which contains pid of
//processes and current status :- 0 = running in background
//, 1= dead , 2 = stopped in background , -1= in foreground.
if(check)
{
processes[pid_counter].pid=pid;
processes[pid_counter].dead=0;
}
if(!check && strlen(token)>0)
{
processes[pid_counter].pid=pid;
processes[pid_counter].dead=-1;
waitpid(pid,&status,0);
tcsetpgrp(STDOUT_FILENO,globalpgid);
tcsetpgrp(STDIN_FILENO,globalpgid);
processes[pid_counter].dead=1;
}
}
}
and these are my handlers
//SIGINT handler
void inthandler(int sig)
{
printf("int handler\n");
int i;
for(i=0;i<=pid_counter;i++)
{
if(processes[i].dead==-1)
{
kill(processes[i].pid,SIGKILL);
break;
}
}
}
//SIGTSTP handler
void tstphandler(int sig)
{
int i;
for(i=0;i<=pid_counter;i++)
{
if(processes[i].dead==-1)
{
processes[i].dead=2;
kill(processes[i].pid, SIGSTOP);
break;
}
}
tcsetpgrp(STDOUT_FILENO,globalpgid);
tcsetpgrp(STDIN_FILENO,globalpgid);
}
My problem is that these signal handlers are not being called from child processes. They are being called with their default action but not with my declared handler.

How can I make a "binary process tree"?

I have a number of process to create. Every son has to create two sons. I used a recursive solution, it works but the number of process created aren't what I want.
This is what I tried:
void generate_kid(int g, int res){
pid_t kid1, kid2;
int status1, status2;
if( res > 0 ){
if( kid1 = fork() ){
if( res > 0){
if( kid2 = fork() ){
}
else {
printf("I am %d, my father is %d\n",getpid(),getppid());
generate_kid(g,res/2-1);
}
}
}
else {
printf("I am %d, my father is %d\n",getpid(),getppid());
generate_kid(g,res/2-1);
}
}
waitpid(kid1,&status1,0);
waitpid(kid2,&status2,0);
}
Try this:
void generate_kid(int res){
pid_t kid1, kid2;
int status1, status2;
if( res > 0 ){
if ((kid1 = fork()) == 0) {
// child
printf("I am %d, my father is %d\n",getpid(),getppid());
// generate half remaining rounded up for odd processes
generate_kid((res-1)/2);
}
else if (kid1 > 0) {
// parent - create second child
if( res > 1){
if ((kid2 = fork()) == 0) {
// child 2
printf("I am %d, my father is %d\n",getpid(),getppid());
// generate half remaining processes
generate_kid((res-2)/2);
}
else if (kid2 > 0){
// parent 2
waitpid(kid2,&status2,0);
}
}
waitpid(kid1,&status1,0);
}
}
}

Resources