Command fork() - getting the PID of the child process

Hello all... I'm a little confused...
I have a C code that I need to call from inside another C program.
I'm using the following structure inside the main function:

int pid;
if ((pid = fork()) < 0) {
cout << "Error\n";
}
else if (pid == 0){
cout << "Child\n";
system("./Program");
}
else {
cout << "Father\n";
system("ls");
//system("kill PID");
}

The program "./program" is an infinite loop, i.e. only stop killing the process. Now comes the problem. How to kill the process created in the child fork? When I look for it in the running processes I'm able to see its PID and use the command "kill PID" in the shell. But I want to put this command just after "system("ls")", in the father's "else".

Does anybody know how to get the "./program" PID?

THanks in advance,
Ricardo.
In the parent, pid already contains the process ID of the child (unless an error occurred, in which case pid < 0).
You mean the "pid" value, that comes from "pid = fork();", rigth?
But, when I show the pid value it gives me the PID of the "bash"... I think that is the parent, right?
If I kill the process identified by the value stored in "pid", I don't kill the "./program", it still there.
Did you undertand what I mean?
The problem you have stumbled across with the system() call (actually there are a few) is that system launches a shell which in turn launches the program you want to run.

What fork does is create an exact duplicate of the process that called it, so when fork() is called it is in one process, when it returns it is in two processes and the only way you can tell the difference from within the code is the fork() return value.

So in you code above all you are doing is killing the duplicate process. The shell and ./program resulting from the system() remain unaffected.

I would suggest not using system() but one of the exec() family of calls; for example execv() within the child branch.
What these calls do is to replace the program the current process is running with a new program so the pid returned by fork() really is the process running ./program.
your code would look like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
int pid;
if ((pid = fork()) < 0) {
    cout << "Error\n";
}
else if (pid == 0) {
    cout << "Child\n";
    execv("./Program", NULL);
}
else {
    cout << "Father\n";
    system("ls");
//system("kill PID");
}


BTW kill is also a C API call (man -s2 kill) so you don't need to use system() to call it.
So:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <sys/types.h>
#include <signal.h>
#include <unistd.h>

int pid;
if ((pid = fork()) < 0) {
    cout << "Error\n";
}
else if (pid == 0) {
    cout << "Child\n";
    execv("./Program", NULL);
}
else {
    cout << "Father\n";
    system("ls");
    kill(pid, SIGTERM);
}


The header files may be different on your system, check your man pages.

Hope this helps
Hi bnbertha!!

Thanks for your reply! That almost worked!

I still having a little problem... lets consider the code you wrote to me, but with one more command.
I added the line -- cout << "ENDING\n"; -- it should not be showed until I kill the process "./program".
It's because the "./program" has an infinite while loop { while(true) }.
This way, only after killing the process, the line with ENDING should be executed.
But, the line is immediately executed after the command execv that initializes the "./program".
When I check the running processes, the "./program" was really finished. But, It wasn't me... look at the "father part" of the code that I've not considered the kill command yet.
What could it be? I am looking for the answers in documentation about the usage of exec command family, but I've found no answers yet.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <sys/types.h>
#include <signal.h>
#include <unistd.h>

int pid;
if ((pid = fork()) < 0) {
    cout << "Error\n";
}
else if (pid == 0) {
    cout << "Child\n";
    execv("./Program", NULL);

    cout << "ENDING\n";

}
else {
    cout << "Father\n";
    system("ls");
    //kill(pid, SIGTERM);
}


Thanks again for your help.
No, your line cout << "ENDING\n"; is not a good idea. I'm surprised it is shown at all, it must be some sort of clean up or left over as the process switches programs.
When you send a kill to ./program, the process is terminated, the process does not kill that program and return to running this one at the point it left off.

Once you call execv(), the process replaces the program image with a completely new one, in your case ./program and starts the new one from main(). It keep some resources on but not much, open file descriptors and some signal behaviours, that sort of thing. It certainly does not keep any knowledge of the code it was running from the previous program.

It is important to realise a program and process are not the same thing; a process is an execution environment for a program, a sort of wrapper. You can change the program inside that process as many times as you want.

So, the only way to get a cout indicating the ./program is terminating is either from within ./program itself, or if you really want to do it after ./program has terminated, put a SIGCHLD handler in the above code. look up the man page for sigaction() if you're not sure how do do it.

When any program terminates, it sends a SIGCHLD signal to its parent. It is the parents job to pick up the exit status of its child, (if it doesn't the child remains a zombie process). You can use this to pick up the exit status and do your cout. In you SIGCHLD handler call wait(); man -s3c wait to get the exit status of the child.

Hope this helps
Last edited on
Hello again!

Well... it surely helped me ;)

However, I still with the same problem. You said:
When any program terminates, it sends a SIGCHLD signal to its parent.

My problem is that the "program" will not terminate. It is an infinite loop (and, unfortunately, it must be). It is a infinite loop because it stands on monitoring determined event until the program that started it realizes that the time was enough. So, the program is terminated by the same one who created it. Did you understand?

I am trying to find out a way of transmitting a signal from child to parent where the child informs the parent its PID. But, I saw that signal functions use pre-defined signals. Now, I am looking for a way for transmitting this information through a signal or other methodology.

Do you know any way?

Thanks very much again!
You already have the pid

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <sys/types.h>
#include <signal.h>
#include <unistd.h>

int pid;
if ((pid = fork()) < 0) {
    cout << "Error\n";
}
else if (pid == 0) {
    cout << "Child\n";
    execv("./Program", NULL);
}
else {
    cout << "Father\n";
    system("ls");
    kill(pid, SIGTERM);
}

In the last else branch i.e. the parent, fork() has returned the pid of the child it created. So you do not need the child to tell the parent its pid because it knows it already.
Topic archived. No new replies allowed.