Running in same child process two times - c

Can I be running in the same child process two times in the same fork? Ex.
pid_t pid;
pid = fork();
if (pid == 0){
some code here
}else{
some code here
}
wait(NULL)
if (pid ==0){
some code here
}else{
some core here
}

When you leave the if/else, the code runs in both the parent and child. The next if/else again switches to different code in each.
pid_t pid;
pid = fork();
if (pid == 0){
// child code here
}else{
// parent code here
}
wait(NULL) // runs in both
if (pid ==0){
// more child code here
}else{
// more parent code here
}
Unless the child forks another child, wait(NULL) in the child will return immediately (it will return -1 and set errno to ECHILD to indicate that it has no children to wait for). But in the parent process it will wait for the child to exit. So the second if/else block will run immediately in the child, while it will not run in the parent until the child exits.

Related

Background process killing with Parent process in C

I have the following code in my main function
pid_t pid;
pid = fork(); //Two processes are made
if (pid > 0 && runBGflag==0) //Parent process. Waits for child termination and prints exit status
{
int status;
if (waitpid(pid, &status, 0) == pid && WIFEXITED(status))
{
printf("Exitstatus [");
for (int i = 0; i < noOfTokens; i++)
{
printf("%s ", commands[i]);
}
printf("\b] = %d\n", WEXITSTATUS(status));
}
}
else if (pid == 0) //Child process. Executes commands and prints error if something unexpected happened
{
if (runBGflag==1) insertElement(getpid(),ptr);
execvp(commands[0], commands);
printf ("exec: %s\n", strerror(errno));
exit(1);
}
In a nutshell, a child process is made and if the runBackGround flag is set, the parent process will not wait for the child process to exit, but rather continue running. If a background process is made, the PID of the background process is stored in a list. At a later point, this function is called
void delete_zombies(void)
{
pid_t kidpid;
int status;
char buffer[1337];
while ((kidpid = waitpid(-1, &status, WNOHANG)) > 0)
{
removeElement(kidpid,buffer,1337);
printf("Child %ld terminated\n", kidpid);
printf("its command was %s\n",buffer);
}
}
This function simply checks if any child processes have died and in that case deletes them. It will then search for the childs PID in the list, remove it and print it out.
The problem is, the delete_zombies function will find that a child has died and will then try to remove it from the list, but it only finds an empty list, as if the child process never inserted its PID into the list.
This is really strange, because delete_zombies only finds a dead child process, when there was one created with the background flag set, so we know insertElement must have been called, but strangely when the parent checks in the list nothing is there
Is the cause for that, that child process and parent process have seperate lists, or is the PID maybe wrong?

How to check which process is running?

Say I used fork twice to get two child processes. Then, I want to execute the 3 processes (including the parent) differently depending on the process is running. How will this be done in c language?
Will the following works:
Say PID1 is the process id for child 1 and similarly PID2 for child 2, then:
I first created the two child using:
pid1 = fork();
if(pid1 == 0){
PID1=getpid();
}
if(pid1 > 0){
pid2 = fork();
if(pid2 > 0){
printf("\nParent ProcessL %d\n",getpid());
}
else if(pid2 == 0){
PID2=getpid();
}
}
-----------------------------------------------------
further down in my code:
while(/*true for a certain time*/){
if (PID1==getpid()){
//execute the code for child 1
} else if (PID2==getpid()){
// execute code for child 2
} else {
// execute the code for the parent
}
by the way, do processes run randomly or they run in order (fixed time for each)?
It won't because the pid returned by fork() in the child is 0.
The simplest way to achieve your goal is to simply branch off right after each fork().
pit_t PID1, PID2;
if(0>(PID1=fork()) {/*handle error*/}
if(!PID1) _exit(code_for_child1());
if(0>(PID2=fork()) {/*handle error*/}
if(!PID2) _exit(code_for_child2());
/*continue the parent's work*/

Forcing the parent process to run first

On my system(Opensuse) by default the child process always executes first, after fork. There are also ways to force the child process to run first. I would like to know if there is any way to force the parent process to run first?
You can use this method
pid_t pid = fork();
if (pid == -1)
abort();
else if (pid == 0)
{
raise(SIGSTOP); // stop the child
}
else
{
waitpid(pid, NULL, WUNTRACED); // wait until the child is stopped
kill(pid, SIGCONT); // resume the child
}

How to make parent wait for all child processes to finish?

I'm hoping someone could shed some light on how to make the parent wait for ALL child processes to finish before continuing after the fork. I have cleanup code which I want to run but the child processes need to have returned before this can happen.
for (int id=0; id<n; id++) {
if (fork()==0) {
// Child
exit(0);
} else {
// Parent
...
}
...
}
pid_t child_pid, wpid;
int status = 0;
//Father code (before child processes start)
for (int id=0; id<n; id++) {
if ((child_pid = fork()) == 0) {
//child code
exit(0);
}
}
while ((wpid = wait(&status)) > 0); // this way, the father waits for all the child processes
//Father code (After all child processes end)
wait waits for a child process to terminate, and returns that child process's pid. On error (eg when there are no child processes), -1 is returned. So, basically, the code keeps waiting for child processes to finish, until the waiting errors out, and then you know they are all finished.
POSIX defines a function: wait(NULL);. It's the shorthand for waitpid(-1, NULL, 0);, which will suspends the execution of the calling process until any one child process exits.
Here, 1st argument of waitpid indicates wait for any child process to end.
In your case, have the parent call it from within your else branch.
Use waitpid() like this:
pid_t childPid; // the child process that the execution will soon run inside of.
childPid = fork();
if(childPid == 0) // fork succeeded
{
// Do something
exit(0);
}
else if(childPid < 0) // fork failed
{
// log the error
}
else // Main (parent) process after fork succeeds
{
int returnStatus;
waitpid(childPid, &returnStatus, 0); // Parent process waits here for child to terminate.
if (returnStatus == 0) // Verify child process terminated without error.
{
printf("The child process terminated normally.");
}
if (returnStatus == 1)
{
printf("The child process terminated with an error!.");
}
}
Just use:
while(wait(NULL) > 0);
This ensures that you wait for ALL the child processes and only when all have returned, you move to the next instruction.

How to use Fork() to create only 2 child processes?

I'm starting to learn some C and while studying the fork, wait functions I got to a unexpected output. At least for me.
Is there any way to create only 2 child processes from the parent?
Here my code:
#include <sys/types.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/wait.h>
int main ()
{
/* Create the pipe */
int fd [2];
pipe(fd);
pid_t pid;
pid_t pidb;
pid = fork ();
pidb = fork ();
if (pid < 0)
{
printf ("Fork Failed\n");
return -1;
}
else if (pid == 0)
{
//printf("I'm the child\n");
}
else
{
//printf("I'm the parent\n");
}
printf("I'm pid %d\n",getpid());
return 0;
}
And Here is my output:
I'm pid 6763
I'm pid 6765
I'm pid 6764
I'm pid 6766
Please, ignore the pipe part, I haven't gotten that far yet. I'm just trying to create only 2 child processes so I expect 3 "I'm pid ..." outputs only 1 for the parent which I will make wait and 2 child processes that will communicate through a pipe.
Let me know if you see where my error is.
pid = fork (); #1
pidb = fork (); #2
Let us assume the parent process id is 100, the first fork creates another process 101. Now both 100 & 101 continue execution after #1, so they execute second fork. pid 100 reaches #2 creating another process 102. pid 101 reaches #2 creating another process 103. So we end up with 4 processes.
What you should do is something like this.
if(fork()) # parent
if(fork()) #parent
else # child2
else #child1
After you create process , you should check the return value. if you don't , the seconde fork() will be executed by both the parent process and the child process, so you have four processes.
if you want to create 2 child processes , just :
if (pid = fork()) {
if (pid = fork()) {
;
}
}
You can create n child processes like this:
for (i = 0; i < n; ++i) {
pid = fork();
if (pid > 0) { /* I am the parent, create more children */
continue;
} else if (pid == 0) { /* I am a child, get to work */
break;
} else {
printf("fork error\n");
exit(1);
}
}
When a fork statement is executed by the parent, a child process is created as you'd expect. You could say that the child process also executes the fork statement but returns a 0, the parent, however, returns the pid.
All code after the fork statement is executed by both, the parent and the child.
In your case what was happening was that the first fork statement created a child process. So presently there's one parent, P1, and one child, C1.
Now both P1 and C1 encounter the second fork statement. The parent creates another child (c2) as you'd expect, but even the child, c1 creates a child process (c3). So in effect you have P1, C1, C2 and C3, which is why you got 4 print statement outputs.
A good way to think about this is using trees, with each node representing a process, and the root node is the topmost parent.
you can check the value as
if ( pid < 0 )
process creation unsuccessful
this tells if the child process creation was unsuccessful..
fork returns the process id of the child process if getpid() is used from parent process..
You can create a child process within a child process. This way you can have 2 copies of the original parent process.
int main (void) {
pid_t pid, pid2;
int status;
pid = fork();
if (pid == 0) { //child process
pid2 = fork();
int status2;
if (pid2 == 0) { //child of child process
printf("friends!\n");
}
else {
printf("my ");
fflush(stdout);
wait(&status2);
}
}
else { //parent process
printf("Hello ");
fflush(stdout);
wait(&status);
}
return 0;
}
This prints the following:
Hello my friends!

Resources