Get child process id of already running process - c

I'm calling an external program (via pty.js in node) that when it runs it spawns a child process. When the parent process finishes it leaves the child running for quit some time (orphan). I can get the id of the parent process, but would like to get the id of the child that is spawned so I can kill it when the parent quits.
I don't believe there is any way in node to achieve this, so is there anything in C that allows you to get the id of a child, knowing only the parent id. Everything I have found so far relates to getting the child id from the fork() but the fork took place in the external program.
Alternatively I guess I could make a call to ps or pstree / something similar and parse the output but feels like a bit of a hack.
EDIT
It's not nice but I've come up with this so far:
#include <limits.h>
#include <stdio.h>
int main(int argc, char *argv[]) {
int id = atoi(argv[1]);
int i;
for(i = 0; i < INT_MAX; i++) {
if(i != id && getpgid(i) == id) {
printf("Process %d, is a child of %d", i, id);
break;
}
}
}

In node.js you can do it via child_process library. There is a pid member function that returns the spawned child's pid. E.g.
var spawn = require('child_process').spawn,
grep = spawn('grep', ['ssh']);
console.log('Spawned child pid: ' + grep.pid);
grep.stdin.end();
You can also kill the child process with kill.
The pty.js does a fork with a pseudo terminal, which is useful if emulating terminal. Otherwise you should use child_process to spawn/fork new processes.

If you can add this code at the end of parent process :
int i ;
while(1)
{
i = wait();//wait child exit
if(i == -1)//if there is no child process
break;
}
If you can't . Then you need do nothing!
Here is the problem:
If the parent process finished but the children process didn't, those children process called :"orphan process" NOT "zombie". A "zombie process" means a child process finished while the patent process still runs, and the parent process didn't handle the child process's aftermath.
Since system will set "init" become the parent of all "orphan process".The init process will deal with everything . So you need do nothing.!!

Related

C program, creating processes , PID

The task is as follows
Write a program that would run another process in memory and leave it running in an infinite loop. When the program is restarted, it must remove the previously started process from memory (you can use kill).
#include <stdio.h>
#include <unistd.h>
#include <signal.h>
#include <stdlib.h>
#include <spawn.h>
#include <sys/wait.h>
int main(void){
int pid = getpid(); // we find out the PID of the current process and store it in a variable
FILE *file = fopen("example.txt", "r"); // getting information from a file about a child process
int filePid = 0;
fscanf(file, "%d", filePid);
fclose(file);
switch (filePid){
case -1:{ // if there is no child process, then run it and write the PID to a file
filePid = fork();
file = fopen("example.txt", "w");
fprintf(file, "%d", filePid);
fclose(file);
break;
}
case 0:{ // if this process is a child, then we go into an infinite loop
for(;;){
sleep(7); // waiting for seven seconds so that the system is not heavily loaded
}
break;
}
default:{ // if this program is started again with a child process, then we send a signal to the child process
kill(filePid, SIGKILL); // we send a signal to the child process so that it ends, and after that we write the information to the file
file = fopen("example.txt", "w"); // we write information to the file that the child process is missing
fprintf(file, "%d", -1);
fclose(file);
}
}
return EXIT_SUCCESS;
}
/Yes, I have to do it through the qnx operating system./
the errors are as follows..I'm a little confused with getpid, because I haven't used the pid variable anywhere.
and another mistake.
I will be grateful for your help.since I'm a little confused...
UPD:
I can't get the value 0
UPD: how could it execute both cases, i mean "if" and "else" blocks at the same time?
how could it execute both cases, i mean "if" and "else" blocks at the same time?
You have to have a clear understanding of how fork works, when you use fork two identical processes are created parent and child and they run simultaneously, when you say filePid = fork() and if the operation is successful then the parent process will hold the process id of the child process and child process will hold 0. So here in parent process filePid == child process ID and in child process filePid == 0.
See man fork
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 whatever you put in the if (filePid == 0) block will be executed by the child process and whatever you put in the else block will be executed by the parent process simultaneously.
This will be helpful if you want to know more about fork.
fork() system call creates a child process and return its pid so once child is created you have two process running same instruction after fork() one is checking pid is greater which means its parent which gets child pid and in child context OS will set the pid value to 0 so it will enter condition block intended for child

parent process does not wait for the child process (c code)

char array[ARRAY_SIZE];
void child_process_routine(){
int j;
for(j = 0;j<ARRAY_SIZE;j++)
array[j]='d';
}
main()
{
pid_t child_pid;
int i;
for(i = 0;i<ARRAY_SIZE;i++)
array[i]='c';
child_pid = fork();
switch (child_pid) {
case -1:
perror("error");
exit(1);
case 0:
child_process_routine();
exit(0);
default:
wait(NULL);
}
print_array(array);
}
can you explain me why the parent process does not wait for the child process and this gives me the output " cccccc " again? it was changed in the child process into " dddddd "
what does wait(NULL) even do?
how does it supposed to know it should wait for the child process?
The parent process is waiting for the child process.
The child is not a thread, it is a completely different process with its own unique PID and the parent as its Parent PID. The child and the parent do not share the same array, the child has its own copy since it is a different process (not a thread of the same process). So when you set the array to 'd' in the child it does not affect the array in the parent process.
Try putting a sleep(20) in the child process flow right before it exits, and a printf() just before the parent wait(). You will see that your application pauses as the parent is waiting for the child to finish.
fork() creates a different process but parent share the same process context.
but if you try to change anything in the stack segment of parent it makes a copy of that and creates a separate stack for child process, but all the resources like data segment, code segment, etc are not copied for child process. They both share it.
This copying on changing the data after fork is called "copy on write"
Parent process is waiting for child process to finish. But its printig for both parent and child separately and different data for both

Determining if a process is a child or parent process (not using return value of fork)

How to write a programm to show whether it's a child or parent process after the fork() is used?
I need to find other way then checking the return value of fork() or getpid() function.
I know e.g. that process resource utilizations (getrusage(2)) and CPU time counters (times(2)) are reset to zero in the child. How i can use for example that knowledge (or other child-parents differences) to determine my problem?
Thank you for your help!
Setup a signal handler for SIGCHLD in one of the processes and end the other one. If the SIGCHLD handler gets called you know the child died. If not the parent died.
Another (less distructive) way it to call wait(). If it returns ECHLD no child is around, thus the calling process is the child. If it blocks, at least one child is around, thus the calling process is the parent.
Or call waitpid() with PID of the other process. The same logic on the result as for wait() applies.
You could exploit the fact that the parent will be a process group leader (and thus its pid will be the same as its process group id) while the child will be a member of that process group and thus its pid will be different from the process group id:
#include <stdio.h>
#include <unistd.h>
main(int argc, char **argv) {
char *self = NULL;
fork(); /* looking at return value would be cheating */
int pid = getpid();
int pgid = getpgid(0);
if (pid == pgid)
self = "Parent";
else
self = "Child";
printf("%s pid = %d pgid = %d\n", self, pid, pgid);
}
Running yields:
$ ./pgid
Parent pid = 29400 pgid = 29400
Child pid = 29401 pgid = 29400
This does of course still use getpid() but not in the same way you describe above.
On Linux, you might also use proc(5). The process of pid 1234 is described by the directory /proc/1234/ and you could read sequentially and parse the /proc/1234/status pseudo-file to get all that information.
To understand a bit more, read the proc(5) man page, then type
cat /proc/self/status
cat /proc/$$/status
cat /proc/self/maps
cat /proc/$$/maps
in a terminal, and try to understand the output. You might parse it programmatically (e.g. with  FILE*f = fopen("/proc/1234/status","r"); then do some fgets or fscanf on f; then fclose(f);)

C/C++ program to kill all child processes of a parent process in UNIX?

I have a function which takes input parameter as PID.
e.g .
bool KillProcessTree (int ParentPID)
{
}
Now I want to write the definition of the above function, which will 1st get all the child processes and then kill them.
Is there any API in Unix which will take parent PID and will return the number of child processes created by the parent process?
There is no standard Unix API to retrieve the list of child processes of a given process.
You can list all the processes on the system with their parent process, and build the process tree from that. The portable way to do this is to run the command
ps -e -o ppid= -o pid=
and parse the output (popen followed by a loop of scanf("%ld %ld\n") will do). Store the data as a finite map from PPID to PID, then walk the tree to collect the list of descendants of the process you're interested in.
If any of the processes concerned forks or exits during your processing, you may miss it. If you're unlucky, a process may exit and its PID may get reused while you're doing all this. Also, if process P forks a child process Q which forks a grandchild R, and then Q exits, R's PPID will be set to 1, so you won't detect that R was originally a descendant of P.
In a nutshell: whatever your problem is, this is very probably the wrong approach.
Unix has a feature to deal with this: process groups. There's a good chance that process groups are the answer to the problem you're trying to solve. You can atomically send signal signal_number to all the processes in a process group with kill(-pgid, signal_number).
You should arrange for all the processes you want to kill to belong to the same process group, and for the processes you don't want to kill not to belong to that process group. Make the parent process call setsid or setpgid, then kill the process group.
I would simply store all the child pids when fork(), in an array of pid_t in the parent process.
after then, kill all by looping that array.
pid_t all_child[10]; // you should not define a fixed length array, you can use pointer.
if((pid = fork()) == 0)
{
//child processes
}
else
{
//parent process
all_pid[counter] = pid;
}
When killing,
for( i = 0; i < counter; i++)
{
kill(all_pid[i], SIGTERM);
}

Using fork() in C?

I have been asked this question for homework, and am having trouble figuring it out. If anyone can help me i would really appreciate it.
What Linux library function is like a fork(), but the parent process is terminated?
I'm fairly certain that whoever assigned you this homework is looking for the exec() family of functions, from the POSIX API header <unistd.h>, because there is nothing else that more closely resembles the sort of functionality you describe.
The exec() family of functions executes a new process and replaces the currently running process address space with the newly executed process.
From the man page:
The exec() family of functions replaces the current process image with
a new process image.
It's not exactly the same as "terminating" the parent process, but in practice it results in a similar situation where the parent process address space is erased (replaced) with the address space of the child process.
What Linux library function is like a fork(), but the parent process
is terminated?
The parent process should not terminate because , it must wait for the child processes to finish executing , after which they will be in a state called "zombie state", now it is the responsibility of the parent to clean up the leftovers of the child process. The parent process can terminate without cleaning up the child processes, but then, it is not a proper way to do it, as the exit status of the child processes should be collected and checked by the parent process.
Here is an example, to demonstrate , what i just said...
#include<stdio.h>
#include<unistd.h>
#include<sys/wait.h>
int main()
{
pid_t cpid = 1 ;
int status;
cpid = fork();
// Load a application to the child using execl() , and finish the job
printf("Parent waiting for child to terminate\n");
int wait_stat = waitpid(-1,&status,0); // Parent will hang here till all child processes finish executing..
if (wait_stat < 0)
{
perror("waitpid error");
exit(-1);
}
// WIFEXITED and WEXITSTATUS are macros to get exit status information, of the child process
if (WIFEXITED (status))
{
printf("Child of id %u cleaned up\n",wait_stat);
printf("Exit status of application = %u\n",WEXITSTATUS(status));
}
}

Resources