Home > database >  Fork() and Wait() with execvp() in C
Fork() and Wait() with execvp() in C

Time:04-06

I'm am trying to use the fork method to call a different program and wait until it completes, I tried to check what is the problem and it seems that the wait function doesn't wait to the childReturns and it makes doesn't print the answer. (the assignment was to loop compare method until ctrl c )

the program I call is a comparator that compares 2 strings.

the problem is that the wait func doesn't wait for the child the compile is GCC

#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <unistd.h>
#include <sys/wait.h>

#define LINELEN (80)

char *mygets(char *buf, int len);
char *progName(char *prog);
int main(int argc, char *argv[])
{
    char *args[3];
    char str1[LINELEN   1];
    char str2[LINELEN   1];
    int childReturns;
    if (argc != 2)
        return -1;

    char *prog = progName(argv[1]);
    if (prog == NULL)
        return -1;
    args[0] = prog;
    while (1)
    {
        printf("Enter string:");
        if (mygets(str1, LINELEN) == NULL)
            break;
        printf("Enter  string:");
        if (mygets(str2, LINELEN) == NULL)
            break;
        args[1] = str1;
        args[2] = str2;
        int processId = fork();
        if (processId == 0)
            execvp(prog, args);
        else
        {
            wait(&childReturns); // Wait for the child
            printf("Child  code is %d\n", WEXITSTATUS(childReturns));
        }
    }
    free(prog);
    return 0;
}
char *progName(char *prog)
{
    char *filePath = (char *)malloc(strlen(prog)   3);
    if (!filePath)
        return NULL;
    strcpy(filePath, "./");
    strcat(filePath, prog);
    return filePath;
}

char *mygets(char *buf, int len)
{
    char *retval;

    retval = fgets(buf, len, stdin);
    buf[len] = '\0';
    if (buf[strlen(buf) - 1] == 10) /* trim \r */
        buf[strlen(buf) - 1] = '\0';
    else if (retval)
        while (getchar() != '\n')
            ; /* get to eol */

    return retval;
} ```

CodePudding user response:

fork() system call duplicates the mother process. The resulting child process and the parent process will have their own address spaces. So child process can not modify childReturns variable of the parent.

Additionally, wait(NULL) waits for child processes to end.

CodePudding user response:

As Jonathan Leffler said the problem was with the args, execvp() needs that the array off args has in the end NULL.

and that fixed the problem.

the Right code :

    char str1[LINELEN   1];
    char str2[LINELEN   1];
    int childReturns = 1;
    if (argc != 2)
        return -1;

    char *prog = progName(argv[1]);
    if (prog == NULL)
        return -1;
    char *args[4];
    args[3] = NULL;
    args[0] = prog;
    while (1)
    {
        printf("Enter string:");
        if (mygets(str1, LINELEN) == NULL)
            break;
        printf("Enter  string:");
        if (mygets(str2, LINELEN) == NULL)
            break;
        args[1] = str1;
        args[2] = str2;
        int processId = fork();
        if (processId == 0)
        {
            execvp(prog, args);
        }
        else
        {
            wait(&childReturns); // Wait for the child
            printf("Child  code is %d\n", WEXITSTATUS(childReturns));
        }
    }
    free(prog);
    return 0;```

CodePudding user response:

Try chaining these lines:

        if (processId == 0)
            execvp(prog, args);
        else

To these:

        if (processId == 0) {
            execvp(prog, args);
            perror(prog);
            abort();
        } else

Also, note that WEXITSTATUS, is only valid if WIFEXITTED() is true. In this case, when your child process abort()'s, it will not be true. So

            wait(&childReturns); // Wait for the child
            printf("Child  code is %d\n", 

needs a bit more work, like:

     if (WIFEXITTED(childReturns)) {
         printf("Child code is %d\n", WEXITSTATUS(childReturns));
     } else if (WIFSIGNALED(childReturns)) {
         printf("Child killed by signal %d\n", WTERMSIG(childReturns);
     } else {
         printf("Child suffered %#x\n", childReturns);
     }

But, your real problem is why is execvp() failing? Look carefully at how big your args array is. Does it match the documentation?

  • Related