How to make sure that the signal was received before continuing - c

I have a few children process, I need to send a signal to the parent and make sure the signal was received before continuing
#define CHILD 0
int n = 0;
void handler(int sig) {
n--;
signal(SIGCHLD, handler);
}
int main(int argc, char * argv[]) {
int p ;
signal(SIGCHLD, handler);
if(argc == 2) {
int k = atoi(argv[1]);
n = k;
while(k-- != 0) {
p = fork();
if(p == CHILD) {
srand(time(NULL));
int r = 1 +(rand()%10);
printf("No:%d %d Child PID: %d times.%d\n",k,n, getpid(),r);
// int rai = raise(SIGCHLD);
printf("rai: %d %d\n", rai, n);
sleep(r);
exit(1);
}
}
} else {
puts("Please provide k num of zombie to be generated\n");
}
while(p > CHILD && n > 0) {
printf("sleeping 2 %d\n", n);
sleep(2);
}
return EXIT_SUCCESS;
}
How can I be sure that the parent catch all the SIGCHILD signals
Imports were omitted on purpose

Related

Child process not waking up after a sigsuspend (C)

I have to create a program that generates 2 childs and each of them has to generate a random number. After that the child who generated the lowest number has to send a SIGUSR1 to the other child. In my case i wanna send a SIGCONT to child 1 to wake him up so that he can send SIGUSR1 to the other process but child 1 doesn't wake up.. any help? Thanks in advance.
#include <unistd.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <stdbool.h>
#define N 2
int getRand(int upper)
{
srand(time(0));
int random;
random = rand() % upper;
return random;
}
void sighandler(int signo)
{
if (signo == SIGUSR1)
{
printf("Received SIGUSR1, my PID is %d\n\n", getpid());
exit(0);
}
if (signo == SIGUSR2)
{
printf("Received SIGUSR2.. I woke up! (My PID is %d)\n\n", getpid());
}
}
int main (int argc, char **argv)
{
int i, r, m, b;
int status = 0;
int tabcpid[N], ppid, wpid;
int fd[2], fdbool[2]; //fd [0 = read] [1 = write]
sigset_t set, zeromask;
struct sigaction action;
//Gestione segnali
sigemptyset(&zeromask);
sigemptyset(&action.sa_mask);
action.sa_handler = sighandler;
action.sa_flags = 0;
sigemptyset(&set);
sigaddset(&set, SIGUSR1);
sigprocmask(SIG_BLOCK, &set, NULL);
if (sigaction(SIGUSR1, &action, NULL) == -1)
{
perror("Error while doing sigaction.\n\n");
}
if (pipe(fd) == -1)
{
printf("Error opening pipe fd!\n\n");
exit(1);
}
if (pipe(fdbool) == -1)
{
printf("Error opening pipe fdbool!\n\n");
exit(1);
}
printf("\nPipes opened successfully. Forking ...\n\n");
sleep(2);
for (i = 0; i < N; i++)
{
if ((tabcpid[i] = fork()) == 0) //Child code
{
int n = atoi(argv[1]);
m = getRand(n);
b = 20;
ppid = getppid();
printf("I'm the son process #%d with PID: %d\n", i + 1, getpid());
printf("Random number in interval 0 - %d: %d\n\n", n, m);
sleep(2);
if (i == 0)
{
close(fd[0]);
write(fd[1], &m, sizeof(int));
close(fd[1]);
printf("Suspending..\n\n");
sigsuspend(&zeromask);
printf("So' ripartitoo\n\n");
/*
close(fdbool[1]);
read(fdbool[0], &b, sizeof(int));
close(fdbool[0]);
printf("--- b value: %d\n\n", b);
if (b == 0)
{
printf("I'm the process %d and I got the lowest number, SIGUSR1 sent to my brother.\n\n", getpid());
kill(tabcpid[1], SIGUSR1);
}
sleep(2);
*/
}
else
{
close(fd[1]);
read(fd[0], &r, sizeof(int));
close(fd[0]);
int lower = (r < m) ? r : m;
int igotlower = (m < r) ? 1 : 0;
printf("--- igotlower value: %d\n\n", igotlower);
close(fdbool[0]);
write(fdbool[1], &igotlower, sizeof(int));
close(fdbool[1]);
//printf("Got %d from other child process, while i got %d.\nThe smallest number is %d.\nMy PID is %d and the other process' PID is %d.\n\n", r, m, lower, getpid(), tabcpid[0]);
//sleep(2);
if (igotlower == 1)
{
printf("I'm the process %d and I got the lowest number, SIGUSR1 sent to my brother..\n\n", getpid());
kill(tabcpid[0], SIGUSR1);
sigsuspend(&zeromask);
}
else
{
printf("I'm sending SIGCONT to %d\n\n", tabcpid[0]);
kill(tabcpid[0], SIGCONT);
sigsuspend(&zeromask);
}
}
sleep(2);
}
sleep(2);
}
wait(&status);
close(fdbool[1]);
read(fdbool[0], &b, sizeof(int));
close(fdbool[0]);
kill(tabcpid[b], SIGUSR1);
wait(&status);
printf("It's me the father... it's all over, we're done!\n\n");
sleep(2);
return 0;
}

How Can I use fork() recursively?

I've been programming this over and over again and I've had trouble learning how to work with fork() in order to generate child processes recursively. I started programming some pretty complicated stuff and I decided to start over again with something way more simple.
I just started learning about processes and I've had trouble understanding them.
The program is designed to fork a tree of processes, however , I must fork from the root two processes which will fork , on the left side 3 children processes, and on the right side 4 children processes. These processes must fork 3 and 4, respectively, processes of their own.
My issue with this is that the program can fork the processes, however only one process on each side is fathering all of the children on their respective side.
Any help you could give me would be great, please tell me if I'm not being clear enough.
#include <unistd.h>
#include <stdio.h>
#include <fcntl.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <sys/types.h>
/* Prototypes */
void three_children();
void four_children();
int main()
{
pid_t process;
int status,n;
printf("Number of levels: \n");
scanf("%d", &n);
for (int i = 0; i < n ; i++) {
process = fork();
switch (process) {
case -1:
printf("Error\n");
break;
case 0:
if (i == 0) {
printf("Left\n");
three_children(process, status);
}
if (i == 1) {
printf("Right\n");
three_children(process, status);
}
printf("Hi I'm a child PID: %d, my father is PPID: %d\n", getpid(), getppid());
exit(0);
default:
printf("I'm a father PPID: %d\n", getppid());
break;
}
}
}
void four_children(pid_t process, int status)
{
for (int j = 0; j < 4; j++) {
process = fork();
switch (process) {
case -1:
printf("Error\n");
break;
case 0:
printf("I'm child: %d, and my father is: %d\n(four children)\n", getpid(), getppid());
exit(0);
break;
default:
printf("I'm a father process: %d\n", getpid());
four_children(process, status);
for (int j = 0; j < 3; j++) {
wait(&status);
}
break;
}
}
}
void three_children(pid_t process, int status)
{
for (int k = 0; k < 3; k++) {
process = fork();
switch (process) {
case -1:
printf("Error\n");
break;
case 0:
printf("I'm a child: %d, and my father is: %d\n(three children )\n", getpid(), getppid());
exit(0);
break;
default:
printf("I'm father %d\n", getpid());
three_child(process, status);
for (int j = 0; j < 3; j++) {
wait(&status);
}
break;
}
}
}
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
typedef struct Node
{
int childrenCount;
struct Node* child[0];
} Node;
Node* makeNode(int children)
{
Node* result = (Node*)malloc(sizeof(Node) + sizeof(Node*) * children);
if (!result) {
exit(1);
}
result->childrenCount = children;
for(int loop = 0;loop < children; ++loop) {
result->child[loop] = NULL;
}
return result;
}
void buildTree(int indent, pid_t parent, Node* node);
void createChild(int indent, pid_t parent, Node* node, int childIndex)
{
pid_t pid = fork();
if (pid == -1) {
exit(1);
}
if (pid == 0) {
buildTree(indent + 1, getpid(), node->child[childIndex]);
srand(parent * 10 + childIndex);
exit(rand());
}
for(int ind = 0; ind < indent; ++ind) {
fprintf(stderr, " ");
}
fprintf(stderr, "Parent: %d Spawned %d\n", parent, pid);
}
void buildTree(int indent, pid_t parent, Node* node)
{
for(int ind = 0; ind < indent; ++ind) {
fprintf(stderr, " ");
}
fprintf(stderr, "Parent %d Has %d Children\n", parent, node->childrenCount);
for(int loop = 0; loop < node->childrenCount; ++loop) {
createChild(indent, parent, node, loop);
}
for(int loop = 0; loop < node->childrenCount; ++loop) {
int status;
int child = wait(&status);
for(int ind = 0; ind < indent; ++ind) {
fprintf(stderr, " ");
}
fprintf(stderr, "Parent: %d Reaped %d with status %d\n", parent, child, status);
}
}
int main()
{
Node* root = makeNode(2);
root->child[0] = makeNode(3);
for(int loopChild = 0;loopChild < 3; ++loopChild) {
root->child[0]->child[loopChild] = makeNode(3);
for(int loopGrandChild = 0;loopGrandChild < 3; ++loopGrandChild) {
root->child[0]->child[loopChild]->child[loopGrandChild] = makeNode(0);
}
}
root->child[1] = makeNode(4);
for(int loopChild = 0;loopChild < 4; ++loopChild) {
root->child[1]->child[loopChild] = makeNode(4);
for(int loopGrandChild = 0;loopGrandChild < 4; ++loopGrandChild) {
root->child[1]->child[loopChild]->child[loopGrandChild] = makeNode(0);
}
}
fprintf(stderr, "Start\n");
buildTree(0, getpid(), root);
fprintf(stderr, "Stop\n");
}

Controlling processes execution using signals

I was given this particular task:
Using SIGCONT, SIGSTOP, and SIGCHLD, write a program that accepts
through argv[] a list of commands (none of them has arguments) and
runs the commands in a round-robin style, alternating commands in
1-second intervals.
To achieve it, I tried this:
int dead_children = 0;
int nr_processes;
void inc_dead () {
printf("I, %d, died\n", getpid());
dead_children++;
if (dead_children == nr_processes)
_exit(0);
}
int main (int argc, char *argv[]) {
int pids[argc - 1];
nr_processes = argc - 1;
signal(SIGCHLD, inc_dead);
for (int i = 1; i < argc; i++) {
pid_t pid;
if ( (pid = fork()) == -1 ) {
perror("fork");
return EXIT_FAILURE;
}
if ( !pid ) {
pause();
execlp(argv[i], argv[i], (char *) NULL);
perror("exec");
_exit(1);
}
pids[i - 1] = pid;
}
while (dead_children < nr_processes)
for (int j = 0; j < argc - 1; j++) {
kill(pids[j], SIGCONT);
sleep(1);
kill(pids[j], SIGSTOP);
}
return EXIT_SUCCESS;
}
I tried to run this code with very simple program that would allow me to verify task's correctness:
int main (void) {
int i = 5;
while (i-- > 0) {
printf("This is %d saying HI!\n", getpid());
sleep(1);
}
return EXIT_SUCCESS;
}
However, this does not work. I noticed that after creation, child processes never left pause() instruction, even though parent is sending a SIGCONT. Any thoughts on how to achieve the goal?

SIGUSR1 - kill sigaction in C

In the C language create a program that creates two processes and connects them via pipe.
The first descendant redirects its' stdout into the pipe and writes (space separated) pairs of random numbers into it (function rand). Delay the output of the numbers by 1 second.
The second descendant redirects the pipe output to it's stdin, redirects it's stdout into a file called out.txt in the current directory.
The parent process waits 5 seconds and then sends SIGUSR1 to the first process (number generator). This should perform a correct termination of both processes. It waits for the sub-processes to terminate (wait function) and terminates itself.
I really need help with:
The first descendant has to treat the SIGUSR1 signal (sigaction function) and in case of receiving such signal it prints a string “TERMINATED” to it's stderr and terminates.
FILE *file;
file = fopen(NAZEV, "a+");
int pipefd[2];
pipe(pipefd);
pid_t pid1;
int retcode;
pid1=fork();
if(pid1 == 0) // child 1
{
close(roura[0]);
printf("child1...\n");
dup2(roura[1], STDOUT_FILENO);
int i = 0;
while(i < 6)
{
i++;
int a = rand();
int b = rand();
sleep(1);
printf("%d %d\n", a, b);
}
close(roura[1]);
exit(45);
}
else if (pid1 < 0)
{
printf("Fork selhal\n");
exit(2);
}
else
{
pid_t pid2;
pid2 = fork();
if (pid2 == 0) //child 2
{
close(roura[1]);
dup2(roura[0], STDIN_FILENO);
printf("child2...\n");
int i = 0;
while(i < 5)
{
i++;
int c;
int d;
scanf("%d %d", &c, &d);
printf("%d %d\n", c, d);
fprintf(file,"%d %d\n", c, d);
}
printf("child2 end\n");
exit(0);
}
else if (pid2 < 0)
{
printf("Fork error\n");
exit(2);
}else
{
sleep(5);
kill(pid1, SIGUSR1);
wait(&pid1); //wait for child 1
wait(&pid2); //wait for child 2
printf("parent end\n");
exit(0);
}
}
exit(0);
}
Adda signal handler to sigusr1 that prints to stderr and exits.
Try this, adapted to compile in cygwin:
#include <stdio.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#ifndef STDIN_FILENO
# define STDIN_FILENO 0
#endif
#ifndef STDOUT_FILENO
# define STDOUT_FILENO 1
#endif
void sig_handler(){
fprintf(stderr,"TERMINATED");
exit(0);
}
void main(int argc, char ** argv){
FILE *file;
file = fopen("NAZEV", "a+");
int pipefd[2];
int roura[2] ;
pipe(pipefd);
pid_t pid1;
int retcode;
pid1=fork();
if(pid1 == 0) // child 1
{
close(roura[0]);
printf("child1...\n");
dup2(roura[1], STDOUT_FILENO);
if (signal(SIGUSR1, sig_handler) == SIG_ERR){
printf("\ncan't catch SIGUSR1\n");
exit(13);
}
int i = 0;
while(i < 6)
{
i++;
int a = rand();
int b = rand();
sleep(1);
printf("%d %d\n", a, b);
}
close(roura[1]);
exit(45);
}
else if (pid1 < 0)
{
printf("Fork selhal\n");
exit(2);
}
else
{
pid_t pid2;
pid2 = fork();
if (pid2 == 0) //child 2
{
close(roura[1]);
dup2(roura[0], STDIN_FILENO);
printf("child2...\n");
int i = 0;
while(i < 5)
{
i++;
int c;
int d;
scanf("%d %d", &c, &d);
printf("%d %d\n", c, d);
fprintf(file,"%d %d\n", c, d);
}
printf("child2 end\n");
exit(0);
}
else if (pid2 < 0)
{
printf("Fork error\n");
exit(2);
}else
{
sleep(5);
kill(pid1, SIGUSR1);
wait(&pid1); //wait for child 1
wait(&pid2); //wait for child 2
printf("parent end\n");
exit(0);
}
}
exit(0);
}
You need to register a signal handler using sigaction if you want to override the default action. For SIGUSR1, the default action is to terminate the process.

How do I fork a maximum of 5 child processes of the parent at any one time?

I have the following code, which I'm trying to only allow a maximum of 5 children to run at a time, but I can't figure out how to decrement the child count when a child exits.
struct {
char *s1;
char *s2;
} s[] = {
{"one", "oneB"},
{"two", "twoB"},
{"three", "thr4eeB"},
{"asdf", "3th43reeB"},
{"asdfasdf", "thr33eeB"},
{"asdfasdfasdf", "thdfdreeB"},
{"af3c3", "thrasdfeeB"},
{"fec33", "threfdeB"},
{NULL, NULL}
};
int main(int argc, char *argv[])
{
int i, im5, children = 0;
int pid = fork();
for (i = 0; s[i].s2; i++)
{
im5 = 0;
switch (pid)
{
case -1:
{
printf("Error\n");
exit(255);
}
case 0:
{
printf("%s -> %s\n", s[i].s1, s[i].s2);
if (i==5) im5 = 1;
printf("%d\n", im5);
sleep(i);
exit(1);
}
default:
{ // Here is where I need to sleep the parent until chilren < 5
// so where do i decrement children so that it gets modified in the parent process?
while(children > 5)
sleep(1);
children++;
pid = fork();
}
}
}
return 1;
}
Revised version seems to work based on comments
struct {
char *s1;
char *s2;
} s[] = {
{"one", "oneB"},
{"two", "twoB"},
{"three", "thr4eeB"},
{"asdf", "3th43reeB"},
{"asdfasdf", "thr33eeB"},
{"asdfasdfasdf", "thdfdreeB"},
{"af3c3", "thrasdfeeB"},
{"fec33", "threfdeB"},
{NULL, NULL}
};
pthread_mutex_t children_count_lock;
int children = 0;
int main(int argc, char *argv[])
{
int i, im5;
int pid = fork();
for (i = 0; s[i].s2; i++)
{
im5 = 0;
switch (pid)
{
case -1:
{
printf("Error\n");
exit(255);
}
case 0:
{
printf("%s -> %s\n", s[i].s1, s[i].s2);
if (i==5) im5 = 1;
printf("%d\n", im5);
sleep(i);
pthread_mutex_lock(&children_count_lock);
children = children - 1;
if (children < 0) children = 0;
pthread_mutex_unlock(&children_count_lock);
exit(1);
}
default:
{
if (children > 4)
wait();
pthread_mutex_lock(&children_count_lock);
children++;
pthread_mutex_unlock(&children_count_lock);
pid = fork();
}
}
}
return 1;
}
The wait() family of functions will suspend the parent until a child process exits (do that instead of sleeping).
No, you don't need critical sections at all - the child and parent don't share memory. All your need is something like this in your default case:
default:
{
children++; // Last fork() was successful
while (children >= 5)
{
int status;
// Wait for one child to exit
if (wait(&status) == 0)
{
children--;
}
}
pid = fork();
}
(Forget what I said before about initialising children to 1, I didn't notice that children++ was supposed to be before the while loop).
Once you get your initial 5 children running, you probably want to use wait() to wait for a child process to finish, at which point you can start a new child.
Call wait() in the parent. This will block until one of the children exits.

Resources