forking and pid - c

The code:
int main(void)
{
printf("pid: %d\n", getpid());
pid = fork();
if (pid < 0) {
fprintf(stderr, "Fork Failed!");
exit(-1);
} else if (pid == 0) {
execv("sum", argv);
} else {
printf(" pid: %d\n", pid);
wait(NULL);
}
}
The output:
pid: 280
pid: 281
The question:
Why are the two pid's different. I thought they should be the same because the parent is what is executing in the else block and the parent is what is executing before the fork so they should be the same, no?

RETURN VALUE
On success, the PID of the child process is returned in the parent,
and 0 is returned in the child. On failure, -1 is returned in the parent,
no child process is created, and errno is set appropriately.
So, in the parent process, fork() returns the pid of the child process that was created.

I won't repeat nos's answer, as he's entirely correct. But I'd point out that any program can retrieve it's own PID with the getpid system call. So there's no reason for the fork to return you own PID. Instead, you may want to know the PID of the process you just forked off, which may be difficult to obtain if it wasn't returned (to the parent) by fork.

Related

kill(pid,SIGTERM) terminates child process, although pid is of parent

I'm learning about process allocation.
Take this code block for example:
int main(){
pid_t pid = fork();
if(pid == 0){
while(1)
printf("Child ");
} else {
for(int i = 0; i<1000;i++)
printf("Parent ");
kill(pid,SIGTERM);
printf("\n%d \n ", pid);
}
}
pid = 0 is the child process, pid > 0 is the parent process. kill(pid,SIGTERM) is executed by the parent with it's own pid, yet it kills the child and not itself. Why?
As #Siguza mentioned in the comments, you should re-read the documentation of fork. fork returns a positive value of pid to the parent process. That value is the PID of the child process. Therefore, kill(pid, SIGTERM) sends the signal to the child and not the parent.

Where did the zombie process go?

int main() {
pid_t pid;
printf("Parent: %d\n", getpid());
pid = fork();
if (pid == -1) {
perror("fork");
goto clean_up;
} else if (pid > 0) {
sleep(3);
} else {
printf("Child Parent: %d\n", getppid());
printf("Child: %d\n", getpid());
printf("Exiting...\n");
}
clean_up:
return 0;
}
I wanted to create zombie process on purpose (of course for experimenting/learning). After the child exits, the parent doesn't wait()s for the child. So, I'm expecting zombie to show up, in ps -ef | grep zombie.o. But for some reason it is not showing up. What could be the possible reasons?
When the parent exits, all its children (alive or zombie) are assigned PID 1 as their new parent. See the _exit(2) man page: " any children of the process are inherited by process 1".
PID 1 is normally the init daemon, and if it's working properly then it should always wait() for its children. So zombie children will be reaped immediately, and children that are still running will be reaped as soon as they exit.
If you want to create a long-lived zombie, the parent needs to remain alive but not calling wait().

fork() and parent/child process ids

I am a bit confused about why the child process in the following two programs is showing different parents ids.
First program:
int main ( void ) {
int pid, fpid, ppid;
fpid = fork ();
pid = getpid();
ppid = getppid();
printf ("fpid is %d\n", fpid);
sleep(5);
if (fpid > 0){
printf ("\nThis is Parent. My pid %d. My parent's pid %d\n",pid,ppid);
}
else if (fpid ==0){
sleep(1);
printf ("\nThis is Child. My pid %d. My parent's pid %d\n",pid,ppid);
}
else
printf ("fork failed\n");
return (0);
}
Output:
fpid is 53560
fpid is 0
This is Parent. My pid 53559. My parent's pid 44632
MacBook-Pro:~/Desktop/$
This is Child. My pid 53560. My parent's pid 53559
Second program:
int main ( void ) {
int pid, fpid, ppid;
fpid = fork ();
printf ("fpid is is %d\n", fpid);
sleep(5);
if (fpid > 0){
pid = getpid();
ppid = getppid();
printf ("\nThis is Parent. My pid %d. My parent's pid %d\n",pid,ppid);
}
else if (fpid ==0){
sleep(1);
pid = getpid();
ppid = getppid();
printf ("\nThis is Child. My pid %d. My parent's pid %d\n",pid,ppid);
}
else
printf ("fork failed\n");
return (0);
}
Output:
fpid is is 53635
fpid is is 0
This is Parent. My pid 53634. My parent's pid 44632
MacBook-Pro:~/Desktop$
This is Child. My pid 53635. My parent's pid 1
I understand that process 1 is the process that takes over as a parent once the original parent terminates. I guess what I want to know is: isn't the parent process being finished before the child process can process its printf in both cases? Shouldn't the outputs be the same?
Since parent and child processes run concurrently, the order of execution depends on runtime. One of them can finish earlier. When parent finishes before child reaches its getppid(), child process would be adopted by init. Hence the parent id 1.
To see child's actual parent process id:
Let the parent wait for its child termination using wait() or waitpid(), or
Let parent sleep for some perceivable amount like sleep(120) after 'This is parent' printf().
isn't the parent process being finished before the child process can process it's printf in both cases?
Very likely so, but not absolutely certain. You cannot ensure that by sleep()ing for any length of time.
Shouldn't the outputs be the same?
They could be the same, but they are unlikely to be. It's important to note when in each program getppid() is called. The parent process ID reported is the one that applied at the time of the call; it is not necessarily still applicable later, when the value is printed.

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?

wait() and exit() with parent-child processes

A fork has already occurred in code:
if (pid == 0) {
printf("I am child PID %d\n", getpid());
exit(EXIT_SUCCESS);
} else {
pid_t child;
int status;
//need wait() function that gets child pid and exit status
printf("Child PID %d terminated with return status %d\n", child, status);
}
As commented in the code, I need an appropriate wait function that will wait for child to end and get the PID and resulting exit status code of the child. Thanks!
You can use wait(), or waitpid() (same page, really).
Or, if you're on BSD, wait3(), or wait4() (but not, AFAIK, wait2()).

Resources