More Information on Child Process Termination? - c

I googled for answer but all the threads I found seemed to suggest using an alternative way to terminate a child process: the _Exit() function.
I wonder if using "return 0;" truly terminate the child process? I tested that in my program (I have waitpid() in the parent process to catch the termination of the child process), and it seemed to work just fine.
So can someone please confirm on this question? Does a return statement truly terminate a process like the exit function or it simply sends a signal indicating the calling process is "done" while the process is actually still running?
Thanks in advance,
Dan
Sample Code:
pid = fork()
if (pid == 0) // child process
{
// do some operation
return 0; // Does this terminate the child process?
}
else if (pid > 0) // parent process
{
waitpid(pid, &status, 0);
// do some operation
}

Using the return statement inside the main function will immediately terminate the process and return the value specified. The process is terminated completely.
int main (int argc, char **argv) {
return 2;
return 1;
}
This program never reaches the second return statement, and the value 2 is returned to the caller.
EDIT - Example from when the fork happens inside another function
However if the return statement is not inside the main function, the child process will not terminate until it has reached down into main() again. The code below will output:
Child process will now return 2
Child process returns to parent process: 2
Parent process will now return 1
Code (tested on Linux):
pid_t pid;
int fork_function() {
pid = fork();
if (pid == 0) {
return 2;
}
else {
int status;
waitpid (pid, &status, 0);
printf ("Child process returns to parent process: %i\n", WEXITSTATUS(status));
}
return 1;
}
int main (int argc, char **argv) {
int result = fork_function();
if (pid == 0) {
printf ("Child process will now return %i\n", result);
}
else {
printf ("Parent process will now return %i\n", result);
}
return result;
}

Related

Amount of process

Do I understand correctly that 2 processes are created in the code below? Since one fork () call creates one thread. There are two such calls in the code, therefore, the process is created 2?
#include <stdio.h>
#include <stdlib.h>
int main() {
int x,y;
pid_t pidl, pid2;
x = 2;
y = 3;
printf ("Single process, x=$d\n",x);
pidl = fork();
if(pidl == 0) {
printf ("New, x=%d\n",x);
exit (0);
}
if(pid1 < 0){
printf("Cannot create");
exit (1);
}
pid2=fork();
if(pid2 == 0) {
printf ("New, y=%d\n",y);
exit (0);
}
if(pid2 < 0){
printf("Cannot create");
exit (1);
}
return 0;
}
Yes. This code create two child process.
However you do not make the relation between parent and child processes by using wait function.
Therefore result of code change variously.
Child process 1 can print result before / after parent process terminated.
Child process 2 can print result before / after parent process terminated.
Maybe this variable result confuse you.

How do I count children processes that end successfully?

I want to write a C program that asks the user for an integer and stores it in a variable n. Then, the main process creates two
child processes (both must be children of the main process). One child exits successfully if n>10 and unsuccessfully
otherwise, whereas the other child exits successfully if n>20 and unsuccessfully otherwise. The main process must print
how many of its children ended successfully.
This is what I have so far.
#include <stdio.h>
void main (void)
{
int n;
printf("Give me a number: ");
scanf("%d", &n);
pid_t child_a, child_b;
child_a = fork();
if (child_a == 0) {
if (n>10) {
exit(1)
}else{
exit(0)
}
} else {
child_b = fork();
if (child_b == 0) {
if (n>20){
exit(1)
}else{
exit(0)
}
} else {
/* Parent Code */
}
}
}
But how do I count how many child processes end successfully?
You need to use wait() command, system call wait() function blocks the calling process until one of its child processes exits or a signal is received.
int status;
pid_t pid = wait(&status);
printf("Exit = %d, child = %d\n", WEXITSTATUS(status), pid);
see example at:
fork() and wait() with two child processes
and 2nd example using wait() and WEXITSTATUS()
Linux fork() and wait()
Also more about what happen with multiple cores scheduling of processes:
fork() and wait() calls

How to properly fork() a process

I'm trying to understand how to properly used fork() and execvp() to execute a command. So far I have the following code:
When I run ./test vim myFile.c it correctly opens myFile.c but I get strange behavior. It seems as though there are two processes running because whenever I enter anything it seems to happen twice. Why is this?
int main (int argc, char* argv[]) {
int fdin, pid, w, status;
fdin = 0;
if ((pid = fork()) < 0)
errorExit (EXIT_FAILURE);
execvp(argv[0],argv);
do {
w = waitpid(cpid, &status, WUNTRACED | WCONTINUED);
if (w == -1) {
perror("waitpid");
exit(EXIT_FAILURE);
}
if (WIFEXITED(status)) {
printf("exited, status=%d\n", WEXITSTATUS(status));
} else if (WIFSIGNALED(status)) {
printf("killed by signal %d\n", WTERMSIG(status));
} else if (WIFSTOPPED(status)) {
printf("stopped by signal %d\n", WSTOPSIG(status));
} else if (WIFCONTINUED(status)) {
printf("continued\n");
}
} while (!WIFEXITED(status) && !WIFSIGNALED(status))
}
When you call fork(), you create two almost completely identical processes, the parent process and the child process. The only difference between these two processes is the return value of fork(), which returns 0 to the child process and the pid of the child to the parent.
Hence, assuming fork succeeded, fork will return a nonnegative integer to both the parent and child process in line 4. Then, both the parent and child process will execute line 6, the execvp, and hence, you end up with two different processes running your vim myFile.c, causing all the problems you described.
The standard idiom is something like:
if ((pid = fork()) < 0) {
// Handle fork error
}
else if (pid == 0) {
// Child process
execvp(...);
}
else {
// Parent process
w = waitpid(pid, ...);
}
Since the return value for fork is 0 for the child, after fork succeeds, the test (pid == 0) will be true for the child, so execvp will be called.
For the parent, fork returns the pid of the child, so the check (pid == 0), which still get executed, is false, so the else condition is executed, causing the parent to wait for the child.
Both parent and child in your program get execvp():
if ((pid = fork()) < 0)
errorExit (EXIT_FAILURE);
execvp(argv[0],argv);
You should check, if you are in parent with pid != 0, and if you are in child otherwise.
You should look at the return value of fork, after a successful fork you will have two running processes at the same position in your program. The child process will get a return value of 0, the parent will get a return value which is the pid of the child. Most likely you want to do different things in the child process and the parent process.
You might also want to think again about how execvp is called. Do you really want to give "./test" as the first argument to execvp?

Forking in Linux and the use of setsid()

I have a sample code and I'm at loss in understanding how to figure out what's happening.
I'm only showing relevant parts. The problem is make_daemon().
From what I understand about forking is that code from close(0) onwards is executed by the child which should have a pid == 0.
What happens when the code hits return -1? Does the code return to the parent or does it exit? Does the child p process code execute if(share) in Monitor()?
This code is an extract from Monitor.c in mdadm.
Thanks in advance for any help.
int Monitor( struct mddev_dev *devlist,
char *mailaddr, char *alert_cmd,
struct context *c,
int daemonise, int oneshot,
int dosyslog, char *pidfile, int increments,
int share )
{
if (daemonise) {
int rv = make_daemon(pidfile);
if (rv >= 0)
return rv;
}
if (share)
if (check_one_sharer(c->scan))
return 1;
/* etc .... */
}
static int make_daemon(char *pidfile)
{
int pid = fork();
if (pid > 0) {
if (!pidfile)
printf("%d\n", pid);
else {
FILE *pid_file;
pid_file=fopen(pidfile, "w");
if (!pid_file)
perror("cannot create pid file");
else {
fprintf(pid_file,"%d\n", pid);
fclose(pid_file);
}
}
return 0;
}
if (pid < 0) {
perror("daemonise");
return 1;
}
close(0);
open("/dev/null", O_RDWR);
dup2(0,1);
dup2(0,2);
setsid();
return -1;
}
fork can return three types of return values:
a positive number: this only happens in the parent: it is the pid of a successfully created child.
zero: this is only returned in the child and indicates that this code now executes in the child. This is not the pid of the child, use getpid to obtain the pid of the child.
a negative value (commonly -1). This is also only ever returned in the parent and indicates that fork failed for whatever reason and no child was created.
As to what your code does: yes the child will continue at close(0); provided that a child was indeed created.
When your cild hits return -1 it will return to whatever function called make_daemon back in the parent and will continue execution at that point. Normally forked children would do whatever they are supposed to do and then call exit in order not to mess up what the parent was doing.

Interprocess Communication fork() - Timing wait() and/or sleep()

I've been asked to develop the consumer (client) side to a producer (server), where the producer creates processes, waits until the consumer has read shared memory and deleted processes, then passes control back to the producer for the killing of processes and the shutting down of the shared memory block.
I've researched the difference between sleep and wait, and realise that as soon as fork() is called, the child process begins running.
The below code is after the creation of processes and checks if they're parent processes. If they are, they wait(0). *Now for my question, how do I know where the code in the consumer starts to be executed, and how do I pass it back? *
else if(pid > 0)
{
wait(0);
}
Below can be seen the main loop the producer uses.
int noToCreate = atoi(argv[2]); // (user inputs on cmd line "./prod 20 10 5" - 20 size of shared mem, 10 process to be created, 5 processes to be deleted)
while(*memSig != 2)
{
while(*memSig == 1) // set memsignature to sleep while..
{
sleep(1);
}
for(B = 0; B < noToCreate; B++)
{
pid = fork();
if(pid == -1)
{
perror("Error forking");
exit(1);
}
else if(pid > 0)
{
wait(0);
}
else
{
srand(getpid());
while(x == 0)
{
if(*randNum == 101)
{
*randNum = rand() % (100 -
1) + 1;
*pidNum = getpid();
printf("priority: %d
Process ID: %d \n", *randNum, *pidNum);
x = 1;
}
else
{
*randNum++;
*pidNum++;
}
}
exit(0);
}
} /* Closes main for loop */
if(*memSig == 0)
{
*memSig = 1;
}
} /* Closes main while loop */
Thanks a bunch guys :)
wait make parent blocked until any child end .You can use waitpid let parent wait specific child.
When a child process end, it will set a signal SIG_CHILD.
The pid is zero for the child process after the fork, so you are in the child process at your call to the srand function.
The other pid is that for the child process which allows he original thread to wait for the child to finish. If you wish to pass data between the processes consider using a pipe. A popen call returns two file descriptors, one to write end and the other to the read end. Set this up before the fork and the two processes can communicate.
wait makes the parent wait for any child to terminate before going on (preferably use waitpid to wait for a certain child), whereas sleep puts the process to sleep and resumes it, as soon as the time passed as argument is over.
Both calls will make the process block.
And it is NOT said that the child will run immediately, this is indeterminate behavior!
If you want to pass data between producer and consumer, use pipes or *NIX sockets, or use the return-value of exit from the child if a single integer is sufficient.
See man wait, you can get the return value of the child with the macro WEXITSTATUS.
#include <sys/wait.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
int
main(int argc, char *argv[])
{
pid_t cpid, w;
int status;
cpid = fork();
if (cpid == -1) {
perror("fork");
exit(EXIT_FAILURE);
}
if (cpid == 0) { /* Code executed by child */
printf("Child PID is %ld\n", (long) getpid());
if (argc == 1)
pause(); /* Wait for signals */
_exit(atoi(argv[1]));
} else { /* Code executed by parent */
do {
w = waitpid(cpid, &status, WUNTRACED | WCONTINUED);
if (w == -1) {
perror("waitpid");
exit(EXIT_FAILURE);
}
if (WIFEXITED(status)) {
printf("exited, status=%d\n", WEXITSTATUS(status));
} else if (WIFSIGNALED(status)) {
printf("killed by signal %d\n", WTERMSIG(status));
} else if (WIFSTOPPED(status)) {
printf("stopped by signal %d\n", WSTOPSIG(status));
} else if (WIFCONTINUED(status)) {
printf("continued\n");
}
} while (!WIFEXITED(status) && !WIFSIGNALED(status));
exit(EXIT_SUCCESS);
}
}

Resources