Program hanged or stop execution randomly using fork() and signal - c

I have written a program where I have created a child process. Both the parent process and child process do calculation in two parts- parent_part1 , parent_part2 and child_part1, child_part2.
My aim is to run the (parent_part1,child_part1,parent_part2 ,child_part2) sequence for let us say 5 times. For this purpose I have used while(var_child++<10) and while(var_par++<10) and successfully achieved it.
Now, I will define ONE SUCCESSFUL calculation is execution of (parent_part1,child_part1,parent_part2 ,child_part2) sequence for 5 times and display the final correct value.
I want to find such 100 SUCCESSFUL calculation and for the same purpose I have used OUTER loop (i.e., while(t1++<100) ), but I am not getting the SUCCESSFUL calculation for 100 times , sometimes I got 40 SUCCESSFUL result, and hanged after parent_part1 or parent_part2 or child_part1 or child_part2 etc. and some other times I got 20 or 95 SUCCESSFUL result, and hanged after parent_part1 or parent_part2 or child_part1 or child_part2 etc.
What is the reason and how to overcome this ?
Thank you in advance . The program is as below.
#include<stdio.h>
#include<signal.h>
int flagp=0,flagc=0,var_child=0,var_par=0;
void write_child()
{
if(flagc==0)
{
/* do some computation here*/
printf("Child_part1 \n");
flagc=1;
}
else
{
/* do some computation here*/
flagc=0;
printf("Child_part2 \n");
}
}
void write_parent()
{
if(flagp==0)
{
/* do some computation here*/
printf("Parent_part1 \n");
flagp=1;
}
else
{
/* do some computation here*/
printf("Parent_part2 \n");
flagp=0;
}
}
int main(int ac, char **av)
{
printf("Starting...\n");
int t1=0;
pid_t childpid = fork();
printf("childpid=%d,getppid()=%d \n",childpid,getppid());
while(t1++<100)
{
var_child=0;
var_par=0;
if ( childpid == 0 )
{
// child process
printf("\n\nt1=%d ",t1);
while(var_child++<10)
{
kill(getppid(), SIGCONT); //sending singal to parent
signal(SIGCONT, write_child);
pause();
}
}
else
{
//parent process
printf("\n\nt1=%d ",t1);
while(var_par++<10)
{
kill(childpid, SIGCONT); //sending singal to child
signal(SIGCONT, write_parent);
pause();
}
} // end of else
}
return 0;
}

Are you sure this logic is correct?
while(var_par++<10)
Apart from that, you are not catching the signal from the parent process. you are creating a lot of zombie processes when the child terminates and by killing the parent from child, you are creating orphans. Both will take system resources and might hit the upper limit on consecutive executions. Try catching the signal and see how it behaves.

Related

Everytime ctrl + z is pressed a random number is generated

Moving straight to the issue, how do I make Ctrl+z do what the title states?
My program implements a parent process which creates a single child process.
Both processes will display the process ID and once the child terminates a signal is sent to the parent process and the parent signal handler will display a text stating a signal has been captured.
On the child process, on top of displaying the child's process ID, it must generate a random number between 10 and 50 every time Ctrl + z is pressed. So far I can only make the child process generate 1 random number.
Below is my code:
void main() {
int pid;
int x;
int fd[2];
const int MAXLINE=4096;
char line[MAXLINE];
pid=fork();
if (pipe(fd) < 0) {
printf("Pipe error!");
}
if (pid < 0) {
printf("Fork error!");
} else if (pid == 0) { //Child process
signal(SIGTSTP, childsignal_handler);
printf("The process id is: %i\n", getpid());
sleep(1000); //Implemented to wait for a signal
} else {
printf("The process id is: %i\n", getpid()); //Parent process
pause(); //Waits for the Child process to finish
}
}
parent signal handler:
void parentsignal_handler(int signo) { //Signal Handler for the parent process
printf("The signal in the parent process has been captured\n");
}
child signal handler:
void childsignal_handler(int signo) { //Signal Handler for the child process
signal(SIGTSTP, childsignal_handler);
printf("\nThe signal in the child process has been captured\n");
randomnumbergenerator();
pause();
}
The random number generator:
void randomnumbergenerator() { //Random number generator to run everytime Ctrl+z is pressed
//signal(SIGTSTP, childsignal_handler);
int number;
int number2 = 10;
printf("Welcome to random number generator!");
printf("\nRandom number generated = %d\n", rand() % 40 + 10);
}
PS: I have read several documentations regarding various solutions such as sigsuspend, sigprocmask,pause and so on but none of them worked so far.
below are some of the documentations i have read so far:
https://www.gnu.org/software/libc/manual/html_node/Waiting-for-a-Signal.html#Waiting-for-a-Signal
https://man7.org/linux/man-pages/man2/pause.2.html
i need to implement a signal that will detect the child terminating
You don't exactly need to implement a signal; you just need to install the handler that you already have:
signal(SIGCLD, parentsignal_handler);
how do I make Ctrl+z do what the title states?
So far I can only make the child process generate 1 random number.
To prevent the parent process from being suspended (and therewith losing signal delivery), ignore the STOP signal in the parent:
signal(SIGTSTP, SIG_IGN);
And you should really pay attention to Ian Abbott's first comment and remove pause() from the signal handler; otherwise after Ctrl-Z was pressed the program will not end. At the same time change sleep(…) to while (sleep(…)) to keep a timed suspension instead of the unlimited pause().

Synchronizing parent and child in an infinite loop

My goal from the code is the following:
-Generate a random number between a given range
-Make user guess the number using the child process
-Make the parent tell the user if guess should be higher/lower
-If guess is correct give a signal for the child to exit.
Current code:
int main() {
int randomnumber = 1+ rand() % 51;
int guess;
pid_t pid=fork();
bool signal=false;
if(pid<0){
printf("Fork failed");
}
if(pid==0){
printf("Enter your guess: \n");
}
while(1)
{
if(pid==0){
if(signal==true)
exit(0);
scanf("%d", &guess);
}
print("test1"); //put this for debugging purposes and only executed once instead of twice
if(pid>0){
print("test2"); //this doesn't execute so I can conclude that parent isn't executing for some reason
wait(NULL);//before adding this parent used to execute and I got an infinite amount of prints which is normal, adding it made the parent not execute
if(guess>randomnumber){
printf("Guess should be lower");
}
if(guess<randomnumber){
printf("Guess should be higher");
}
if(guess==randomnumber){
printf("WIN");
signal=true;
break;
}
}
}
return 1;
}
Any idea what I can do to synchronize both of them? Why doesn't the parent execute after adding the wait function, it should at least execute the parent before wait(NULL).
As some some users remarked in comments this cannot be done unless I implement inter-process communication or a shared memory.

synchronizing 2 processes

I'm trying to make 2 processes start on a task at the same time (count a number, for example). I set 2 ready flags, one for each process, and perform a while loop to check if both flags are up. Then the 2 processes will start counting after the check is passed. Here's the not working code, which I don't know why:
int p1ready=0;
int p2ready=0;
int onebil = 1000000000;
int main(){
int pid;
int exit_code;
pid=fork();
if(pid==0){
//child1
int count1=0;
p1ready=1; //signal
while(!(p1ready&p2ready))'//wait until 2 processes are both ready
while(count1!=onebil){
count1++;
}
exit(0);
}
else{
pid=fork();
if(pid==0){
//child2
int count2=0;
p2ready=1; //signal
while(!(p1ready&p2ready));//wait until 2 processes are both ready
while(count2!=onebil){
count2++;
}
exit(0);
}
else{
//parent
//do stuff
}
return 0;
}
The problem with this code is, in child1 and child2, only their own ready flag is set to 1. They cannot see the flag of the other child being set. For example, child1 only sees p1ready=1, but p2ready is always 0. Why is this so? How can I fix this?
Thanks in advance!
When you do a fork() each process gets a new address space that is private. Parent and children will not share any data. That's where inter-process communication mechanisms enter.
You might use semaphores. See this links:
semaphore equivalent for processes?.
http://www.csc.villanova.edu/~mdamian/threads/posixsem.html
You can prepare semaphores on parent, have each child wait on it after each fork, and then release them in parent. Both child processes will be released and continue execution at same time. Which ones executes first depends on OS execution scheduler,of course.
#include <stdio.h>
#include <semaphore.h>
#include <unistd.h>
int p1ready=0;
int p2ready=0;
int onebil = 1000000000;
int main(){
int pid;
int exit_code;
// create a semaphore for each child: value=0
sem_t *sem1 = sem_open("test_semaphore", O_CREAT|O_EXCL);
sem_t *sem2 = sem_open("test_semaphore", O_CREAT|O_EXCL);
pid=fork();
if(pid==0){
//child1
// wait on semaphore => blocks if value <= 0
sem_wait(sem1);
int count1=0;
// do work => a function might be better
while(count1!=onebil){
count1++;
}
exit(0);
}
else{
pid=fork();
if(pid==0){
//child2
// wait on semaphore => blocks if value <= 0
sem_wait(sem2);
// do work
int count2=0;
while(count2!=onebil){
count2++;
}
exit(0);
}
else{
//parent
// signal semaphore1 (increment) releasing child 1
sem_post(sem1);
// signal semaphore2 (increment) releasing child 2
sem_post(sem2);
// do work
// wait for child1/child2
int status;
wait(&status); // a child has exited
// do something with status
wait(&status); // another child has exited
// do something with status
}
return 0;
}
The way you are trying to synchronize your processes is not going to work as every process you are creating will have its own copy of p1ready and p2ready.
What you seem to be looking for is some kind of inter process communication. You might want to take a look at http://en.wikipedia.org/wiki/Inter-process_communication to see a list of possible options.
In a simple case like the one mentioned in your question most probably sending both of your child processes a signal from the parent process will be enough, so i suggest you best take a look at that.

parent-child process communication through pipes

I am tryimg to write a C program that will search an array of integers for another given integer. However, to speedup the search, the search is done in parallel by two child processes. The parent process reads in the number of integers, and then the integers in an array. It also reads in the integer to be searched. It then creates two child processes. The first child process searches the first half of the array, and the second child process searches the second half. If the integer is found, its index in the array is sent to the parent through a pipe. If it is not found, a -1 is sent to the parent through a pipe. The parent waits for both child processes to finish and then prints an appropriate message.
I have consulted some books and this is what i came up with. There is a small problem though...the two child processes are running one after the other rather than parallel. what changes should i make?
#include<stdlib.h>
#include<stdio.h>
#include<unistd.h>
#include<sys/ipc.h>
#include <string.h>
void main ()
{
int i,status,num1,num2,num3,num4, fd1[2], fd2[2];
int a[1000];
char b[5],c[5],d[5],e[5];
pid_t pid1,pid2;
printf("\n\n\nEnter how many numbers - ");
scanf("%d",&num1);
//printf("\n\nEnter the %d numbers below -\n",num1);
for (i=0;i<num1;i++)
{
printf("%d : ",i);
scanf("%d",&a[i]);
}
printf("\n\nEnter the number to search - ");
scanf("%d",&num2);
pipe(fd1);
pipe(fd2);
pid1=fork();
if (pid1==0)
{
printf("this is the child 1\n");
for (i=0;i<(num1/2);i++)
{
if (a[i]==num2)
{
printf("found by process 1\n");
sprintf(b,"%d",i);
sprintf(c,"%d",-1);
write(fd1[1],&b,4);
write(fd2[1],&c,4);
//kill(0,1);
break;
}
printf("%d\n",a[i]);
}
_exit ( EXIT_FAILURE ) ;
}
else
if (pid1>0)
{
pid2=fork();
if (pid2==0)
{
printf("this is the child 2\n");
for (i=(num1/2);i<num1;i++)
{
if (a[i]==num2)
{
printf("found by process 2\n");
sprintf(b,"%d",-1);
sprintf(c,"%d",i);
write(fd1[1],&b,4);
write(fd2[1],&c,4);
//kill(0,1);
break;
}
printf("%d\n",a[i]);
}
_exit(EXIT_FAILURE);
}
}
if (waitpid (pid1, &status, 0)>0 && waitpid (pid2, &status, 0)>0)
{
read(fd1[0],d,4);
read(fd2[0],e,4);
num3=atoi(d);
num4=atoi(e);
if (num3>0) printf("value of i is %d\n",num3);
if (num4>0) printf("value of i is %d\n",num4);
}
}
Your code is fine, but remember that processor time is given out in rather large slices. That is, a short computation is often finished before the other process has even received a processor time slice. Insert a few calls to sleep into your loops, and you will see the concurrency.
Are we sure your system has more than one core? If it has only one processor, the processes will run one after the other anyway.

How to run two child processes simultaneously in C?

So I'm getting into Concurrent Programming, but for some reason I can't even get the basics to work. I have a file called fork.c, which contains a method main. In this method main I fork twice, into child processes 1 and 2.
In child 1, I print the character 'A' 50 times.
In child 2, I print the character 'B' 50 times.
When I run my code, I get the output AAAAA...AAAABBBBBB....BBBBBB. But never something like ABABABABABABAB.... In fact, sometimes I even get BBBBB....BBBBAAAA....AAAAA.
So why am I experiencing this behavior? Perhaps I'm going about it completely wrong.
#include <stdlib.h>
#include <stdio.h>
void my_char(char n) {
write(1, &n, 1);
}
int main() {
int status;
pid_t child1, child2;
if (!(child1 = fork())) {
// first childi
int a;
for (a = 0; a < 50; a++) {
my_char('A');
}
exit(0);
} else if (!(child2 = fork())) {
// second child
int a;
for (a = 0; a < 50; a++) {
my_char('B');
}
exit(0);
} else {
// parent
wait(&child1);
wait(&child2);
my_char('\n');
}
return 0;
}
They are running concurrently, but the processes end almost immediately after being started. In other words, they're too short to actually get any real overlap.
EDIT:
The time needed to start another process is longer than the time it takes to run them. Therefore the chance of overlap is small. (there are also buffering issues which I'll omit)
You need each process to do more work than that. Try printing more than 50. Printing more than 10000 will probably be enough.
I think this is much easier to figure how fork() works:
#include <stdlib.h>
#include <stdio.h>
int main() {
pid_t child1, child2;
printf("Start\n");
if (!(child1 = fork())) {
// first childi
printf("\tChild 1\n");
sleep(5);
exit(0);
} else if (!(child2 = fork())) {
// second child
printf("\tChild 2\n");
sleep(5);
exit(0);
} else {
// parent
printf("Parent\n");
wait(&child1);
printf("got exit status from child 1\n");
wait(&child2);
printf("got exit status from child 2\n");
}
return 0;
}
...and here is the output:
Start
Child 1
Parent
Child 2
got exit status from child 1
got exit status from child 1

Resources