I have the following code:
int main(int argc, char **argv)
{
char *program;
char stringa[1000] = "";
int num = 123;
char snum[10];
if (argc != 2) {
printf("Usage: mon fileName\n where fileName is an executable file.\n");
exit(-1);
} else {
program = argv[1];
sprintf(stringa, "./%s", program);
pid_t pid = fork();
if (pid < 0 ) {
perror("fork failed.");
exit(1); }
else if (pid == 0) {
char* args[] = {stringa, NULL};
execv(args[0], args);
}
else {
char procmon_str[] = "./procmon";
num = pid;
sprintf(snum, "%d",num);
pid_t pid2 = fork();
if (pid2 == 0) {
char* args2[] = {procmon_str, snum, NULL};
execv(args2[0], args2); }
else {
printf("PID of child is %s", snum);
int parent_pid = getpid();
printf("PID of parent is %d", parent_pid);}
}}
wait(NULL);
return 0;
}
The name of this program is myProgram
. The argument I provide in the shell is:
./myProgram calc
calc
is another program I want to launch using myProgram
.
myProgram
then executes calc
, takes its PID
and passes that PID
to another program called procmon
that does something with it; that's why I need to fork twice.
However, when I run the code above, I get:
procmon: cannot open /proc/6225/stat, the monitored process is not running anymore
.
How can I fix this?
What does calc
do?
It goes into a for
loop, increments an int
variable and goes to sleep for 3 seconds and repeat that 10 times. So it should run for about 30 seconds.
What does procmon
do?
procmon
simply receives a PID
of a process as an argument and displays the corresponding /proc/PID/stat
file. It works perfectly when you run it by itself.
You have a race condition. You have no guarantee that the first fork()
actually even returns to your parent process before the calc child process finishes executing and exits. You need to synchronize the execution of your processes.
ETA suggestions on where to block and signal
if (pid == 0)
{
// block here waiting for the go-ahead from parent
char* args[] = { stringa, NULL };
execv( args[ 0 ], args );
}
......
else
{
// signal calc child here
printf( "PID of child is %s", snum );
int parent_pid = getpid();
printf( "PID of parent is %d", parent_pid );
}
Learning how to block and signal via interprocess communication is left as an exercise for the questioner.
Didn't notice at first...
Your main process is creating two child processes, proc and prcmon. Your problem is that due to race conditions and schedualling - calc finishes first, so what you want to do is to force calc to wait for its sibling process. You can only wait() on a process that you created... So this way you can't make calc wait for prcmon to finish.
BUT
You can implement some mechanism to make parent process wait on its children and then via pipe pass the return data to other child process. In your case I am not sure. You want in prcmon to get the PID of calc and display it ? I don't know if that is possible as once calc is done, its descriptor is erased and does no longer exist.
A solution to your problem is to make calc do heavy calculation as you only need it alive and not its return value.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With