fork(), runs always the parent first and then the child - unix

im learning about fork() but something is working wrong in my ubuntu. im running this code:
#include <stdio.h>
#include <unistd.h>
int main(int argc, char **argv)
{
printf("--beginning of program\n");
int counter = 0;
pid_t pid = fork();
if (pid == 0)
{
// child process
int i = 0;
for (; i < 5; ++i)
{
printf("child process: counter=%d\n", ++counter);
}
}
else if (pid > 0)
{
// parent process
int j = 0;
for (; j < 5; ++j)
{
printf("parent process: counter=%d\n", ++counter);
}
}
else
{
// fork failed
printf("fork() failed!\n");
return 1;
}
printf("--end of program--\n");
return 0;
}
i know the parent and the child should run their code in no specific order so the code should return something like this:
-beginning of program
parent process: counter=1
parent process: counter=2
parent process: counter=3
child process: counter=1
parent process: counter=4
child process: counter=2
parent process: counter=5
child process: counter=3
child process: counter=4
child process: counter=5
--end of program--
But every time i run the program, they run in what it seems to be the same order. here is a capture of what i get every single time i run this program:
user#user-VirtualBox:~/Documents/S-O$ ./sample
--beginning of program
parent process: counter=1
parent process: counter=2
parent process: counter=3
parent process: counter=4
parent process: counter=5
--end of program--
user#user-VirtualBox:~/Documents/S-O$
child process: counter=1
child process: counter=2
child process: counter=3
child process: counter=4
child process: counter=5
--end of program--
it seems like the parent finish first, and then the child starts. but i guess thats not true. please note that the second shell prompt is opened by the program itself. any ideas of what may be happening?
Edit:
if i put an sleep(1) it works just fine. i still think that with no delay it shouldn't always have the same execution order. even counting until 100, it giver the same thing

Yes parent and children run their code in an almost unpredictable order (remember that there is no randomness), but your scheduler probably choose, after forking, to schedule the parent first and then the child. As both have a very small code, the parent is able to run all of its code, and then the children. To experiment something else you must do something much much more longer after forking in both processes (You will be able to see different interleaving of outputs for example).
The prompt is not produced by your code, but is an effect of it. When the parent process dies, the shell that ran it get control back and prompt you for another command, while in the same time the children is working and pollutes your terminal. The child has become an orphan process. To prevent this, you must tell the parent to wait its child by calling...wait().

Related

fork() has no homogeneous behaviour within shell

I've been testing this simple fork in C:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
int main (int argc, char** argv) {
int id = fork();
pid_t p = getpid();
pid_t pp = getppid();
if (id != 0) {
printf("I'm the parent, fork() gave me %i, my pid is %i and my parent's is %i \n",id,p,pp);
return 0;
}
else {
printf("I'm the child, fork() gave me %i, my pid is %i and my parent's is %i \n",id,p,pp);
return 0;
}
}
I run it on Debian using VSCode and gcc.
Everytime I launch it, i get something like :
I'm the parent, fork() gave me 152911, my pid is 152906 and my parent's is 152890
I'm the child, fork() gave me 0, my pid is 152911 and my parent's is 1
[1] + Done "/usr/bin/gdb" --interpreter=mi --tty=${DbgTerm} 0<"/tmp/Microsoft-MIEngine-In-bdyrp1e2.wm5" 1>"/tmp/Microsoft-MIEngine-Out-vixicyih.jop"
in the VSCode console. But when I invoke this script directly from the console, sometimes something "strange" happens :
me#laptop:~/Desktop/programmesC$ ./test_fork
I'm the parent, fork() gave me 153571, my pid is 153570 and my parent's is 8738
me#laptop:~/Desktop/programmesC$ I'm the child, fork() gave me 0, my pid is 153571 and my parent's is 1
Hence it behaves as if the parent gave the control back to the shell then the child executed. And in the meanwhile the shell has got the result of the children's print() ?
Which would mean that everytime I get a "proper" output (like in case #1), it's the child process who finishes its execution before its parent ? Am I correct or did I miss something ?
The order these three things are queued and ran will appear as if it’s random.
The code returns for both the parent and child. In your case, occasionally the parent ends and the shell is resumed before the child ends.

In double fork, why can't grandchild exit before child exit?

Double Fork
In my understanding, double fork is used when a process wants to fork a background process, but 1. it does not want to wait for it AND 2. the background process should be reaped after it exits.
As a result, double fork only requires parent process waits for child process, which should exit immediately after forking grandchild process, and grandchild process is in charge of the real task as a background process.
Context
According to this excerpt from APUE, the grandchild sleeps 2 seconds to make sure its parent (the child) exits before it exits, so that it will be an orphan and init will take care of it and reap it when it exits.
#include "apue.h"
#include <sys/wait.h>
int
main(void)
{
pid_t pid;
if ((pid = fork()) < 0) {
err_sys("fork error");
} else if (pid == 0) { /* first child */
if ((pid = fork()) < 0)
err_sys("fork error");
else if (pid > 0)
exit(0); /* parent from second fork == first child */
/*
* We're the second child; our parent becomes init as soon
* as our real parent calls exit() in the statement above.
* Here's where we'd continue executing, knowing that when
* we're done, init will reap our status.
*/
sleep(2);
printf("second child, parent pid = %ld\n", (long)getppid());
exit(0);
}
if (waitpid(pid, NULL, 0) != pid) /* wait for first child */
err_sys("waitpid error");
/*
* We're the parent (the original process); we continue executing,
* knowing that we're not the parent of the second child.
*/
exit(0);
}
Problem
Why does grandchild process need to sleep that 2 seconds? Assume it exits before child process exits, it will still be reaped when child process exits according to this question, and parent process still does not need take care of it.
Doesn't that fulfill the original goal of using double fork?
The purpose of the example is to demonstrate that the grandchild's parent becomes process 1 (init) after its original parent exits.
To demonstrate that the grandchild's parent becomes process 1, the grandchild calls getppid and prints the result.
If the grandchild calls getppid before its original parent has exited, then getppid returns something that's not pid 1.
If the grandchild calls getppid after its original parent has exited, then getppid returns 1.
The purpose of the example program is to make #2 happen. So it needs to make sure the original parent has exited before the grandchild calls getppid. It does this by calling sleep(2) in the grandchild.
The grandchild, in a real program, would not sleep(2) there. It would just do its work.
Since this is a toy program, there's no real work for the grandchild to do.

Process reads data before writing into pipe

I am trying to create pipe and use it with fork(). But I m confused in the order of execution.
Process reads data from pipe before anything is written into pipe. Sometimes it runs correctly. But sometimes, reads before writing but still gives correct output.
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
int main(void)
{
int fd[2], nbytes,ret;
pid_t childpid;
char string[] = "Hello, world!\n";
char readbuffer[80];
pipe(fd);
if(!fork())
{
close(fd[0]);
printf("Writing...");
write(fd[1], string, (strlen(string)+1));
exit(0);
}
else{
close(fd[1]);
printf("Reading...");
nbytes = read(fd[0], readbuffer, sizeof(readbuffer));
printf("Received string: %s", readbuffer);
wait(NULL);
}
return 0;
}
It happens because scheduler schedules the parent process before the child and thus
it results in the read operation before write. On the other hand, the output may be
as expected sometimes when scheduler will schedule the child first.
SOLUTION:
1. you need to use synchronisation techniuqes like semaphores in order to synchronise the
parent and the child.
2. or you can make the parent process wait until the child has finished. Consider the
following code :
int child_status; // declare this variable
/* add the following line to the else clause */
else
{
close(fd[1]);
wait(&child_status);
// rest of your code
}
Explanation :
If the parent process is scheduled before the child, then its execution will halt when
it finds the 'wait(&child_status)' statement and will wait for the child to finish
its execution and then proceed further.

why does ptrace singlestep return a too big instruction count when statically linking it?

So, I've already read this article Counting machine instructions of a process using PTRACE_SINGLESTEP, and i understand that dynamically linking a testprogram to my ptrace program will return an instruction count that also counts the initialization of the run-time library. However, I'm trying to get a valid count for my test program, which is:
int main(){
return 0;
}
My ptrace program first also returned 90k+ values, so I changed it to statically linking the used testprogram. The counter is now less, but still over 12k. The program I used to count the instructions is:
#include <sys/ptrace.h>
#include <unistd.h>
#include <stdio.h>
int main() {
long long counter = 1; // machine instruction counter
int wait_val; // child's return value
int pid; // child's process id
int dat;
switch (pid = fork()) { // copy entire parent space in child
case -1: perror("fork");
break;
case 0: // child process starts
ptrace(PTRACE_TRACEME,0,NULL,NULL);
/*
must be called in order to allow the
control over the child process and trace me (child)
0 refers to the parent pid
*/
execl("./returntestprog","returntestprog",NULL);
/*
executes the testprogram and causes
the child to stop and send a signal
to the parent, the parent can now
switch to PTRACE_SINGLESTEP
*/
break;
// child process ends
default: // parent process starts
wait(&wait_val);
if (ptrace(PTRACE_SINGLESTEP, pid, 0, 0) != 0)
perror("ptrace");
/*
switch to singlestep tracing and
release child
if unable call error.
*/
wait(&wait_val);
// parent waits for child to stop at next
// instruction (execl())
while (wait_val == 1407) {
counter++;
if (ptrace(PTRACE_SINGLESTEP, pid, 0, 0) != 0)
perror("ptrace");
/*
switch to singlestep tracing and
release child
if unable call error.
*/
wait(&wait_val);
// wait for next instruction to complete */
}
/*
continue to stop, wait and release until
the child is finished; wait_val != 1407
Low=0177L and High=05 (SIGTRAP)
*/
}
printf("Number of machine instructions : %lld\n", counter);
return 0;
} // end of switch
Any help would be really appreciated as I'm not quite sure if it's working right, or not at all. Once I get this thing started, I want to work on timing analysis with ptrace, but first things first and try to count the number of executed instructions
thanks!
I've kind of figured it out by now. So even when statically linking your code, you try to prevent the libraries to be dynamically linked to your program and thus also included into your count. The other side of it however is that executing your file, or basically invoking under the operating system also takes an enormous amount of instructions. So basically, as long as the instruction count is constant and the same under the same conditions, you can subtract this count (when using a return 0 program for instance) from your original program, to count the real number of instructions.

Why the parentPid is 0x1 in my test code?

I want use pointer to get the pid of parent process with child process of it:
int main(void){
pid_t childPid,*parentPid,pid;
childPid = fork();
if(childPid == 0 ){
printf("[Child] the parent pid is 0x%u\n", *parentPid);
}else if(childPid < 0){
printf("there is something wrong");
}else{
pid = getpid();
printf("[Parent] the pid is 0x%u\n",pid);
parentPid = &pid;
}
return (EXIT_SUCCESS);
}
the output is:
[Parent] the pid is 0x5756
[Child] the parent pid is 0x1
there must be something wrong with my code, any idea?
The child never modifies *parentPid, so it just contains random garbage. If you want your parent PID, call getppid.
Even if you fixed the race condition, the code still wouldn't work. Changing memory in the parent doesn't change that memory in the child unless the memory is shared. If all memory were shared by default, the child and parent would instantly obliterate each other's data and cause total chaos.

Resources