C Pthreads - Parent/Child process - c

I've written a C program that creates a child thread. After creating the child thread, the parent thread should output two messages. The first being "I am the parent" and the second "The parent is done". The same should occur for the child thread "I am the child" and "The child is done". However I want to make sure, the second message of the child is always done before the second message of the parent. How can I achieve this in my code below?
#include <unistd.h>
#include <stdio.h>
#include <pthread.h>
int status = 0;
void *print_child(void *arg)
{
while (status == 0)
{
printf("Signal hasn't changed..\n");
sleep(1);
}
printf("The child has started...\n");
printf("The child is done! \n ");
}
int main()
{
pthread_t child;
pthread_create(&child, NULL, &print_child, NULL);
sleep(2);
printf("The parent has started...\n");
printf("The parent is done! \n");
status++;
if (pthread_join(child, NULL))
{
printf("ERROR");
exit(1);
}
}

Once a thread created it process independently and act like a separate process from the main thread. In your case you are joining the child thread after the statement printf("The parent is done! \n");. It not necessary that operating system will complete the child thread first always. Hence your expected result might not meet always. put a long sleep statement just before statement printf("The parent is done! \n"); and check but still not necessary that child will complete first.

The reason your code doesn't work is because you aren't making sure that the second printf in the parent thread is being executed before the second printf in the child thread.
A good option in this case would be to use mutexes. In this case, you can use a mutex to act as a 'guard' before the second printf, so the code will look something like this:
pthread_mutex_t print_lock;
...
In print_child:
// can only acquire after the parent releases, therefore guaranteeing that
// the parent thread has already printed the second statement
pthread_mutex_lock(&print_lock);
printf("The child is done! \n ");
pthread_mutex_unlock(&print_lock);
In main:
// lock it before the child thread is
// started, therefore guaranteeing the parent will have initial ownership
pthread_mutex_lock(&print_lock);
pthread_create(&child, NULL, &print_child, NULL);
sleep(2);
printf("The parent has started...\n");
printf("The parent is done! \n");
pthread_mutex_unlock(&print_lock);
...

Just put following line after printf("The parent has started...\n"); and before printf("The parent is done! \n");:
status++;
if (pthread_join(child, NULL))
{
printf("ERROR");
exit(1);
}
So corrected code will be as following:
#include <unistd.h>
#include <stdio.h>
#include <pthread.h>
int status = 0;
void *print_child(void *arg)
{
while (status == 0)
{
printf("Signal hasn't changed..\n");
sleep(1);
}
printf("The child has started...\n");
printf("The child is done! \n ");
}
int main()
{
pthread_t child;
pthread_create(&child, NULL, &print_child, NULL);
sleep(2);
printf("The parent has started...\n");
status++;
if (pthread_join(child, NULL))
{
printf("ERROR");
exit(1);
}
printf("The parent is done! \n");
return 0;
}

Related

Fork wait and pipe in C

I have this assignment where we are supposed to create a specific amount of child processes, lets say 3, and make the parent wait for each child to finish. Also we're supposed to have a pipe that all processes write to so that once the parent is done waiting, it would use the pipe's to output the sum of all the children's results.
This is my code so far but it seems that wait(NULL) isn't working as expected. I am not sure what I'm doing wrong.
#include <stdio.h>
#include <sys/wait.h>
#include <unistd.h>
int main() {
for (int i=0; i<3; i++) {
pid_t child = fork();
if (child > 0) {
printf("Child %d created\n", child);
wait(NULL);
printf("Child %d terminated\n", child);
}
}
printf("Parent terminated\n");
return 0;
}
First of all, it's better to first run all child processes and then wait for all of them, instead of waiting for each one sequentially.
In addition, the child processes should exit immediately and not keep running the forked code.
Thirdly, you must pay attention and wait for all children after the loop, and not only for the first one that terminates:
#include <stdio.h>
#include <sys/wait.h>
#include <unistd.h>
int main() {
for (int i=0; i<3; i++) {
pid_t child = fork();
if (child > 0) {
printf("Child %d created\n", child);
}
else if (child == 0) {
printf("In child %d. Bye bye\n", i);
return 0; // exit the child process
}
}
while (wait(NULL) > 0); // wait for all child processes
printf("Parent terminated\n");
return 0;
}
EDIT:
The code above is just an improvement to the example given in the question. In order to implement the pipe of information from the child processes to the parent, a pipe can be created (using pipe()) and the write-end file descriptor would be accessible from child processes.
Here's a good example to do so.

C Can't signal a child process to continue after `sigsuspend`

I'm trying to create a program where a process forks, creating a child process, and the parent must always finish printing to the screen before the child is finished printing to the screen, no matter what. I also wish to accomplish this using signals instead of pipelining.
It is a similar problem to the question asked here: Explanation of sigsuspend needed
I understand that kill(pid,signal); is to send a signal to that pid and tell it to finish executing and terminate.
The problem is, when it executes, the child doesn't print after the suspend. Heres the code:
int main(void){
pid_t pid;
int i;
pid = fork();
if(pid==0){
sigset_t mask;
sigemptyset(&mask);
sigaddset(&mask,SIGUSR1);
printf("This is the child Process id = %d \n",getpid());
sigsuspend(&mask);
printf("The child is now complete \n");
}
else{
printf("This is the parentProcess id = %d \n",getpid());
printf("The parentProcess is complete\n");
sleep(1);
int j = kill(pid,SIGUSR1);
if (j!=0)
{
perror(NULL);
}
exit(0);
}
}
I have managed to accomplish my task (printing the parent before the child) by using a global variable int x = 0; and a signal handler method void handle1(int s){x = 1;}before the main. In the main I added signal(SIGUSR1,handle1); In the child I removed all the sigset and sigsuspend lines and instead wrote while(x==0){/*do_nothing*/} 1 line before the printf statement. So when the parent executes kill(pid,SIGUSR1) the signal handler which is inherited by the child process also gets executed and sets x=1. So the child now leaves the while loop and can print it's statement.
However I believe it would be helpful to know how to accomplish this task using sigmask_t and sigsuspend() but i cant get it to work that way.
There are 3 problems in your code:
SIGUSR1 is the signal you want to deliver to the child. You can't use sigaddset(&mask,SIGUSR1);, it does exactly the opposite of your intention.
According to POSIX standard sigsuspend() below, you should install a signal handler for SIGUSR1 to make sigsuspend() continue the following code, since the default behavior of SIGUSR1 is termination.
The sigsuspend() function shall replace the current signal mask of the calling thread with the set of signals pointed to by sigmask and then suspend the thread until delivery of a signal whose action is either to execute a signal-catching function or to terminate the process.
It would be better if you collect the child from the parent, otherwise there is a race condition.
The code below will work:
#include <signal.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
void handler(int sig) {}
int main(void){
pid_t pid;
int i;
pid = fork();
signal(SIGUSR1, handler);
if(pid==0){
sigset_t mask;
sigemptyset(&mask);
//sigaddset(&mask,SIGUSR1);
printf("This is the child Process id = %d \n",getpid());
sigsuspend(&mask);
printf("The child is now complete \n");
}
else{
printf("This is the parentProcess id = %d \n",getpid());
printf("The parentProcess is complete\n");
sleep(1);
int j = kill(pid,SIGUSR1);
if (j!=0)
{
perror(NULL);
}
wait(NULL);
exit(0);
}
}
You have a few issues.
Your parent process should wait for the child to complete. This allows for diagnostics (such as properly waiting for the child to print), but is otherwise a bookkeeping task that is a good habit even when the waiting process will just exit:
printf("This is the parentProcess id = %d \n",getpid());
printf("The parentProcess is complete\n");
sleep(1);
int j = kill(pid,SIGUSR1);
if (j!=0)
{
perror(NULL);
exit(0);
}
waitpid(pid, NULL, 0);
exit(0);
Now, you have set SIGUSR1 in your mask to sigsuspend(), which causes the signal to be ignored. This is now more obvious once the parent is made to wait, because the parent will never exit. So, remove the line of code that sets SIGUSR1.
Finally, the default handler for SIGUSR1 will simply cause the process to exit, and so the printf will not get a chance to print. If you want it to print, you should add a signal handler for SIGUSR1. It doesn't have to do anything.
void h (int s) {}
...
sigset_t mask;
sigemptyset(&mask);
//sigaddset(&mask,SIGUSR1);
printf("This is the child Process id = %d \n",getpid());
struct sigaction sa = { .sa_handler = h };
sigaction(SIGUSR1, &sa, NULL);
sigsuspend(&mask);
printf("The child is now complete \n");

how to execute parent befor child thread - pthreads in c

I want to make it so that parent process executes before the child thread does. I'm not sure where I'm going wrong to get the order my program is outputting.
int status = 0;
void *print_child(void *arg)
{
while (status == 0)
{
printf("Signal hasn't changed..\n");
sleep(1);
}
printf("The child has started...\n");
printf("The child is done! \n ");
}
int main()
{
pthread_t child;
pthread_create(&child, NULL, &print_child, NULL);
sleep(2);
printf("The parent has started...\n");
printf("The parent is done! \n");
status++;
if (pthread_join(child, NULL))
{
printf("ERROR");
exit(1);
}
}
OUTPUT:
signal has changed
signal has changed
parent has started
parent is done
child has started
child is done
The simplest way to exclude concurrent execution is a lock. Have the "parent" (original thread) take a lock before calling pthread_create, and only unlock it when it's ready for the "child" (new thread) to to run. The "child" should take the lock before doing anything; it can then unlock it immediately if it wants, or keep it to control access to shared state.

C Programming - Scanf not working in ubuntu

I am writing a C program in Ubuntu 10 to create processes, display process ID and to kill process. I'm using kill() command to kill a process ID that user entered via scanf. However, the scanf is not working at all. I tried to add "space" before %d but nothing happened. Appreciate if anyone can help!
Following are my codes:
include <stdio.h>
include <unistd.h>
include <signal.h>
include <sys/types.h>
include <stdlib.h>
main ()
{
int x;
int pid[10]; // to store fork return value
int p[10]; // to store process ID
// Create 5 new processes and store its process ID
for (x=1;x<=5;x++)
{
if ((pid[x]=fork())==0)
{
p[x]=getpid();
printf("\n I am process: %d, my process ID: %d\n",x,p[x]); // Display process number and PID
}
else
exit(0);
}
{
int y;
y=p[x];
printf("Please enter a process ID to kill: ");
scanf(" %d", &y); //waiting for user input
printf("\nThe process %d is killed.\n",y);
kill(y,9); //Values 9 represents SIGKILL
}
}
Your parent process exits, and so does every process you spawn afterwards (their return value of fork is different than 1 so they exit). If a process has no parent it becomes an "orphan" and has special handling by the OS (some other process adopts it). Are you sure this is the behavior you were looking for?
EDIT:
This is probably what you meant to write:
#include <stdio.h>
#include <unistd.h>
#include <signal.h>
#include <sys/types.h>
#include <stdlib.h>
int main ()
{
int x;
int pid[10]; // to store fork return value
pid_t parent = getpid();
// Create 5 new processes and store its process ID
for (x=1;x<=5;x++)
{
if ((pid[x]=fork())!=0)
{
printf("\n I spawned process: %d, its process ID: %d\n",x,pid[x]); // Display process number and PID
}else{
while(1){}
}
}
if(getpid() == parent){
int y;
y=pid[x];
printf("Please enter a process ID to kill: ");
scanf(" %d", &y); //waiting for user input
printf("\nThe process %d is killed.\n",y);
kill(y,9); //Values 9 represents SIGKILL
}else{
printf("THIS SHOULD NOT HAPPEN!");
}
return 0;
}
fork returns twice, each time in a different process. One very important thing to realize about the two processes is that they do not share memory. That means that by calling getpid in the child and saving that in an array you are unable to see that value in the parent's copy of the variable.
What you most likely want to do is something like:
for (...) {
if ((pid[x]=fork()) == 0) {
printf("child created, pid = %d\n", getpid());
while(1) sleep(1000); /* children will never run outside this loop */
} else {
continue;
}
}
/* this code only runs in the parent */

How to terminate a child process which is running another program by doing exec

I'm doing fork in my main program,and doing exec in the child process which will run another program. Now i want to terminate the child(i.e., the program invoked by exec) and return back to the main program(or parent program). how could i achieve this.. I tried with ctrl+c but its killing parent process and child also.please help me.
/*This is main.c*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <signal.h>
#include <sys/wait.h>
void sig_int(void);
void sig_term(void);
pid_t pid,ppid;
int main(char argc,char **argv){
int n;
char ch;
printf("***********Application to start or stop services**********\n");
do
{
printf("Enter 1 to start service no.1\n");
printf("Enter 2 to start service no.2\n");
printf("Enter 3 to start service no.3\n");
scanf("%d",&n);
if(fork() == 0)
{
switch(n)
{
case 1: printf("starting service no. 1..\n");
printf("checking whether the given service is already running...\n");
// system("./det.sh ./test")
pid = getpid();
printf("child process pid = %d\n",pid);
// signal(SIGINT,(void *)sig_int);
// signal(SIGTERM,(void *)sig_term);
//execl("/var/vR_main","vR_main",argv[1],argv[2],argv[3],argv[4],NULL);
execl("./test","test",0,0);//will run test.c
break;
case 2: printf("starting service no. 2..\n");
break;
case 3: printf("starting service no. 3..\n");
break;
}
}
else
{
int status;
wait(&status);
if (WIFEXITED(status))
printf("CHILD exited with %d\n", WEXITSTATUS(status));
if (WIFSIGNALED(status))
printf("signaled by %d\n", WTERMSIG(status));
if (WIFSTOPPED(status))
printf("stopped by %d\n", WSTOPSIG(status));
// sleep(2);
ppid = getpid();
printf("%d\n",ppid);
// wait();
printf("\nDo you want to continue...y/n:");
scanf(" %c",&ch);
}
}while(ch == 'y');
return 0;
}
void sig_int(void)
{
printf("caught signal\n");
kill(pid,SIGKILL);
// signal(SIGINT,SIG_DFL);
// exit(0);
}
void sig_term(void)
{
printf("killing the process\n");
signal(SIGINT,SIG_DFL);
// exit(0);
}
/*This is test.c*/
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <signal.h>
void sig_int(void);
void sig_term(void);
pid_t pid;
int main()
{
// int a=10,b=40,c=50,max;
pid = getpid();
printf("exec pid = %d\n",pid);
while (1)
{
signal(SIGINT,(void *)sig_int);
signal(SIGTERM,(void *)sig_term);
}
// max=a>b?a>c?a:c:b>c?b:c;
// printf("%d\n",max);
}
void sig_int(void)
{
printf("caught signal\n");
// signal(SIGINT,SIG_DFL);
kill(pid,SIGKILL);
// exit(0);
}
void sig_term(void)
{
printf("killing the process\n");
signal(SIGINT,SIG_DFL);
// exit(0);
}
Now I want to kill "test application" (invoked by exec),and return to the parent process or the "else block" to continue the program.
You need to do the following:
Do a kill(pid, SIGTERM) first - this gives the child process an opportunity to terminate gracefully
Wait a period of time (use sleep). The period of time depends on the time the child process takes to close down gracefully.
Use waitpid(pid, &status, WNOHANG) checking the return value. If the process has not aborted do step 4
Do a kill(pid, SIGKILL) then harvest the zombie by doing waitpid(pid, &status, 0).
These steps ensure that you give the child process to have a signal handler to close down and also ensures that you have no zombie processes.
Either in or outside your program, it is possible to use kill. By including <signal.h>, you can kill a process with a given PID (use the fork return value to do this).
#include <signal.h>
int pid;
switch (pid = fork())
{
case -1:
/* some stuff */
break;
case 0:
/* some stuff */
break;
default:
/* some stuff */
kill(pid, SIGTERM);
}
It is also possible to use kill command in the shell. To find the PID of your child process, you can run ps command.
man kill
The kill() function shall send a signal to a process or a group of processes specified by pid. The signal to be sent is specified by sig and is either one from the list given in <signal.h> or 0. If sig is 0 (the null signal), error checking is performed but no signal is actually sent. The null signal can be used to check the validity of pid.
POSIX defines the kill(2) system call for this:
kill(pid, SIGKILL);

Resources