Question

I am kind of newbie on C++, and working on a simple program on Linux which is supposed to invoke another program in the same directory and get the output of the invoked program without showing output of the invoked program on console. This is the code snippet that I am working on:

    pid_t pid;
    cout<<"General sentance:"<<endl<<sentence<<endl;
    cout<<"==============================="<<endl;
    //int i=system("./Satzoo");
    if(pid=fork()<0)
        cout<<"Process could not be created..."<<endl;
    else
    {
        cout<<pid<<endl;
        execv("./Satzoo",NULL);
    }
    cout<<"General sentance:"<<endl<<sentence<<endl;
    cout<<"==============================="<<endl;

One of the problem I encounter is that I am able to print the first two lines on console but I cant print the last two lines. I think the program stops working when I invoke the Satzoo program. Another thing is that this code invokes Satzoo program twice, I dont know why? I can see the output on screen twice. On the other hand if I use system() instead of execv(), then the Satzoo works only once.

I haven't figured out how to read the output of Satzoo in my program.

Any help is appreciated.

Thanks

Was it helpful?

Solution

You aren't distinguisng between the child and the parent process after the call to fork(). So both the child and the parent run execv() and thus their respective process images are replaced.

You want something more like:

pid_t pid;
printf("before fork\n");

if((pid = fork()) < 0)
{
  printf("an error occurred while forking\n");
}
else if(pid == 0)
{
  /* this is the child */
  printf("the child's pid is: %d\n", getpid());
  execv("./Satzoo",NULL);
  printf("if this line is printed then execv failed\n");
}
else
{
  /* this is the parent */
  printf("parent continues execution\n");
}

OTHER TIPS

The fork() function clones the current process and returns different values in each process. In the "parent" process, it returns the pid of the child. In the child process, it returns zero. So you would normally invoke it using a model like this:

if (fork() > 0) {
    cout << "in parent" << endl;
} else {
    cout << "in child" << endl;
    exit(0);
}

I have omitted error handling in the above.

In your example, both of the above code paths (both parent and child) fall into the else clause of your call to fork(), causing both of them to execv("./Satzoo"). That is why your program runs twice, and why you never reach the statements beyond that.

Instead of using fork() and doing everything manually (properly managing process execution is a fair amount of work), you may be interested in using the popen() function instead:

FILE *in = popen("./Satzoo", "r");
// use "in" like a normal stdio FILE to read the output of Satzoo
pclose(in);

From the fork() manpage:

RETURN VALUE
Upon successful completion, fork() shall return 0 to the child process and shall return the process ID of the child process to the parent process. Both processes shall continue to execute from the fork() function. Otherwise, -1 shall be returned to the parent process, no child process shall be created, and errno shall be set to indicate the error.

You check to make sure it succeeds, but not whether the pid indicates we're in the child or the parent. Thus, both the child and the parent do the same thing twice, which means that your program gets executed twice and the ending text is never printed. You need to check the return value of fork() more than just once.

exec - The exec() family of functions replaces the current process image with a new process image.

system - Blocks on execution of the command. Execution of the calling program continues after the system command returns

There are three return value tests you want with fork

  1. 0: you are the child
  2. -1: error
  3. other: you are the parent

You ran the other program from both the child and the parent...

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top