How to display the pid of a parent process - c

let me start by saying this is my first question on stackoverflow, and I am very new to coding as well, so I appolagize in advance for any shortcomings.
I am trying to find out how a child process can display the parent pid of their own parent process (the child process' grandparent pid)
Here is the code I have, I added a comment that I need to change:
#include <stdio.h>
#include <unistd.h>
#include <sys/wait.h>
int main()
{
int pid, status, status2;
pid = fork();
switch (pid)
{
case -1: // An error has occured during the fork process.
printf("Fork error.");
break;
case 0:
pid = fork();
switch (pid)
{
case -1:
printf("Fork error.");
break;
case 0:
printf("I am the child process C and my pid is %d\n", getpid());
printf("My parent P has pid %d\n", getppid());
printf("My Grandparent G has pid %d\n", //what to put here );
break;
default:
wait(&status);
printf("I am the parent process P and my pid is %d\n", getpid());
printf("My parent G has pid %d\n", getppid());
break;
}
break;
default:
wait(&status2);
printf("I am the Grandparent process G and my pid is %d\n", getpid());
break;
}
}
also, general tips would be appreciated

You could just save the pid in grandparent.
int pid, status, status2;
int pppid = getpid();
pid = fork();
switch (pid) {
....
printf("My parent G has pid %d\n", pppid);
}
or save the pid of getppid() in parent. There is no "standard" way of getting "parent pid of parent pid" so it's just the same as getting pid of any other process. You could inspect /proc/<pid>/stat, something along:
pid_t getppid_of_pid(pid_t pid) {
intmax_t ret = -1;
char *buf;
int r = asprintf(&buf, "/proc/%jd/stat", (intmax_t)pid);
if (r == -1) goto asprintf_err;
FILE *f = fopen(buf, "r");
if (f == NULL) return fopen_err;
if (fscanf(f, "%*s %*s %*s %jd", &ret) != 1) return fscanf_err;
fscanf_err:
fclose(f);
fopen_err:
free(buf);
asprintf_err:
return ret;
}
...
printf("My Grandparent G has pid %jd\n", (intmax_t)getppid_of_pid(getppid()));
See man procfs for explanation of fields in /proc/../stat.

Related

Duplicate printf while forking

I'm using fork to make process tree here's the code:
#include<stdio.h>
#include<unistd.h>
#include<sys/types.h>
#include <sys/wait.h>
#include <stdlib.h>
int main () {
pid_t pid;
printf("Parent of all: %ld\n",(long)getpid());
pid = fork();
if(pid == -1){
perror("fork failed");
exit(EXIT_FAILURE);
}
else if (pid == 0){
pid = fork();
printf("Child with id: %ld and its Parent id: %ld \n", (long)getpid(),(long)getppid());
if(pid > 0){
pid = fork();
printf("Child with id: %ld and its Parent id: %ld \n", (long)getpid(),(long)getppid());
_exit(EXIT_SUCCESS);
}
}
else{
int status;
waitpid(pid, &status, 0);
}
return EXIT_SUCCESS;
}
after else if the printf line passes to a child so i get the same thing printed twice as u can see in results here results can i somehow prevent this from happening?
When you call fork both the parent and child process will continue executing from the same point, which means they will both execute printf("child with id...).

Creating of specific process tree

I'm trying to create a process tree as on image. Down below is my code, that i wrote. It works properly but only a half. The output of my code is on the second screenshot. The problem is, that i don't know, how to make the last generation.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
int main() {
int i;
int j;
pid_t ppid;
pid_t cpid;
ppid = getpid();
printf("I'm the parent, my PID is: %d\n", ppid);
for (i = 0; i < 4; i++) {
ppid = fork();
if (ppid == 0) {
printf("Hello, my PID is: %d, my parent's PID is %d\n", getpid(), getppid());
for(j = 0; j < 2; j++) {
ppid = fork();
if (ppid == 0) {
printf("Hello, my PID is: %d, my parent's PID is %d\n", getpid(), getppid());
sleep(60);
printf("I'm process %d and I'm done\n", getpid());
exit(0);
}
}
sleep(60);
printf("I'm process %d and I'm done\n", getpid());
exit(0);
}
}
sleep(1);
printf("I'm process %d. Waiting for one of my children to complete", getpid());
wait(NULL);
printf("Eltern: I'm done\n");
printf("... and bye. \n");
}
If I understand your question correct, you just need to add a fork in the inner most if-statement.
if (ppid == 0) {
printf("Hello, my PID is: %d, my parent's PID is %d\n", getpid(), getppid());
// Add one more fork here
sleep(60);
printf("I'm process %d and I'm done\n", getpid());
exit(0);
}

getpid() returns unexpected value

I am trying to run this piece of hello world code :
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
char string1[] = "\n Hello";
char string2[] = " World.\n";
int main(void)
{
int childpid;
if((childpid = fork() ) == -1){
printf("\n Can't fork.\n");
exit(0);
}
else if(childpid == 0){ /* Child process */
printf("\n Child: My pid = %d, Parent pid = %d \n", getpid(), getppid());
exit(0);
}
else{ /* Parent Process */
printf("\n Parent: Child pid = %d, My pid = %d, Parent pid = %d \n", childpid, getpid(),getppid());
exit(0);
}
}
The output I am getting is different each time with regard to the child's parent PID :
~$ ./f
Parent: Child pid = 6394, My pid = 6393, Parent pid = 27383
Child: My pid = 6394, Parent pid = 1842
~$ ./f
Parent: Child pid = 6398, My pid = 6397, Parent pid = 27383
Child: My pid = 6398, Parent pid = 6397
When I checked to which process the pid = 1842 belongs to I found that it is the pid of /sbin/upstart --user. Anybody has an interpretation of these results please.
You have race condition. Sometimes, your parent finishes a little bit faster, these are the cases when you see this strange result (different parent ID).
Sleep for a while inside parent and see what happens.
In fact, you can wait for your child: waitpid
...
int status;
waitpid(childpid, &status, 0);
printf("\n Parent: Child pid = %d, My pid = %d, Parent pid = %d \n", childpid, getpid(),getppid());
exit(0);
...

exit() the program from parent before child process has terminated

I have a C server. This server has to handle multiple connections and user's input (through a simple ncurses GUI). So I created two childs.
My problem comes when from the main menu of the user interface, I need to exit the program (then terminate the second child process -which handles the connections- from the first child process).
I'll try to explain myself with a little example:
int main(){
pid_t pid;
int status1, status2;
if((pid = fork()) < 0){
perror("main fork failure:");
exit(1);
}
if(pid == 0){
pid = fork();
if(pid == 0){
/*
some stuff the second child does while
the first child is already running
*/
}
/* this is the first child */
int choice;
choice = menu();
switch(choice){
case 1:
break;
case 2:
/*
HERE I have to exit (from the first child first,
and from the program then): how can I kill the
second child that is running to prevent
zombie processes?
*/
// kill() which pid?
exit(2);
break;
}
wait(&status2);
}
wait(&status1);
return 0;
}
So, how can I kill it if I don't know the second child pid from the first child?
In your code, you reuse the variable pid, but fortunately, the non-zero pid is the one you need to signal.
Hence:
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <unistd.h>
extern int menu(void);
static void wait_for_pid(int pid)
{
int status;
int corpse;
while ((corpse = wait(&status)) >= 0 && corpse != pid)
printf("Unexpected child %d exited with status 0x%.4X\n", corpse, status);
if (corpse == pid)
printf("Child %d exited with status 0x%.4X\n", corpse, status);
else
printf("Child %d died without its death being tracked\n", pid);
}
int main(void)
{
pid_t pid;
if ((pid = fork()) < 0)
{
perror("main fork failure:");
exit(1);
}
if (pid == 0)
{
if ((pid = fork()) < 0)
{
perror("child fork failure:");
exit(1);
}
if (pid == 0)
{
pause(); /* Do nothing until signalled */
exit(0);
}
/* this is the first child */
int choice = menu();
switch (choice)
{
case 1:
/* action 1 */
break;
case 2:
kill(pid, SIGTERM);
exit(2);
/*NOTREACHED*/
}
wait_for_pid(pid);
exit(0);
}
wait_for_pid(pid);
return 0;
}
The loop in the wait_for_pid() function should be overkill for the child, but the parent process could have children it doesn't know about under some circumstances — unlikely but not impossible circumstances.
The use of pause() in the second child is simply writing some code; it is not useful and would not therefore be what you'd write there. Writing the comment /* action 1 */ is likewise dummy code; you'd replace it with code that does something useful. I'd probably have functions to call for the first child and the second child, rather than embedding much code in main(). I assume that it's written as shown to create an MCVE (Minimal, Complete, Verifiable Example); thank you for keeping the code small.
The code above was untested because there was no menu() function. The code below has a menu function — not that it is very interactive.
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <unistd.h>
extern int menu(void);
int menu(void)
{
printf("Dozing...\n");
sleep(1);
printf("Menu option 2 chosen\n");
return 2;
}
static void wait_for_pid(int pid)
{
int status;
int corpse;
int curpid = getpid();
printf("%d: waiting for children to die\n", curpid);
while ((corpse = wait(&status)) >= 0 && corpse != pid)
printf("%d: Unexpected child %d exited with status 0x%.4X\n", curpid, corpse, status);
if (corpse == pid)
printf("%d: Child %d exited with status 0x%.4X\n", curpid, corpse, status);
else
printf("%d: Child %d died without its death being tracked\n", curpid, pid);
}
int main(void)
{
pid_t pid;
if ((pid = fork()) < 0)
{
perror("main fork failure:");
exit(1);
}
if (pid == 0)
{
if ((pid = fork()) < 0)
{
perror("child fork failure:");
exit(1);
}
if (pid == 0)
{
printf("Second child (%d) - pausing\n", (int)getpid());
pause(); /* Do nothing until signalled */
printf("Second child (%d) - awake despite no signal handling\n", (int)getpid());
exit(0);
}
/* this is the first child */
printf("First child (%d) - menuing\n", (int)getpid());
int choice = menu();
switch (choice)
{
case 1:
/* action 1 */
break;
case 2:
printf("kill(%d, SIGTERM)\n", pid);
kill(pid, SIGTERM);
wait_for_pid(pid);
exit(2);
/*NOTREACHED*/
}
/* Reached on menu choices != 2 */
/* Probably needs a loop around the menu() - end loop before wait_for_pid() */
wait_for_pid(pid);
exit(0);
}
wait_for_pid(pid);
return 0;
}
When run, a sample output sequence was:
19489: waiting for children to die
First child (19490) - menuing
Dozing...
Second child (19491) - pausing
Menu option 2 chosen
kill(19491, SIGTERM)
19490: waiting for children to die
19490: Child 19491 exited with status 0x000F
19489: Child 19490 exited with status 0x0200
All of which looks as would be expected. You can see the death from SIGTERM in the status 0x000F (SIGTERM is normally 15, and is 15 on macOS Sierra, though AFAIK no standard demands that it is 15). You can see the first child exited normally with status 2 from the 0x0200. You can see that the parent started waiting before the children did anything. And you can see the debugging techniques — copious printing and including the PID most of the time.

Parent/Child process print

I'm writing a C program that creates a child process. After creating the child process, the parent process should ouput two messages: "I am the parent" then it should print "The parent is done". Same for child process "I am 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 to print "The child is done" and "The parent is done" rather than printing their pid?
#include <unistd.h>
#include <stdio.h>
main()
{
int pid, stat_loc;
printf("\nmy pid = %d\n", getpid());
pid = fork();
if (pid == -1)
perror("error in fork");
else if (pid ==0 )
{
printf("\nI am the child process, my pid = %d\n\n", getpid());
}
else
{
printf("\nI am the parent process, my pid = %d\n\n", getpid());
sleep(2);
}
printf("\nThe %d is done\n\n", getpid());
}
You could have a flag variable, that is set in the parent, but then the child clears it. Then simply check for that for the last output.
Something like
int is_parent = 1; // Important to create and initialize before the fork
pid = fork();
if (pid == -1) { ... }
if (pid == 0)
{
printf("\nI am the child process, my pid = %d\n\n", getpid());
in_parent = 0; // We're not in the parent anymore
}
else { ... }
printf("\nThe %s is done\n\n", is_parent ? "parent" : child");
Call wait(2) in the parent process for the child to complete.
else
{
wait(0);
printf("\nI am the parent process, my pid = %d\n\n", getpid());
}
You should check if wait() succeeds and main()'s return type should be int.

Resources