Saucy Goat
Saucy Goat

Reputation: 1675

fork() - have parent process do work without waiting for child process

I'm making a shell in C for a school project that is capable of running processes in parallel if it is commanded to do so.

This is the loop of the shell application that waits for commands:

while (1) {
    action = parseShellArgs();

    if (action == 1) {
        printf("Exiting...\n");
        break;
    } else if (action == 0) {
        int pid = fork();

        if (pid < 0) {
            printf("Failed to fork\n");
        } else if (pid == 0) {
            (*NUM_PROCESSES_RUNNING)++;
            printf("There are %d processes running\n", *NUM_PROCESSES_RUNNING);
            char * solverArgs[] = {"a", shellArgs[1], NULL};    // first element is placeholder for argv[0]
            execv("CircuitRouter-SeqSolver", solverArgs);
            exit(0);
        } else if (pid > 0) {
            if (*NUM_PROCESSES_RUNNING >= MAXCHILDREN) {
                printf("All processes are busy\n");
                continue;
            }
            int status, childpid;

            wait(&status);
            childpid = WEXITSTATUS(status);
            (*NUM_PROCESSES_RUNNING)--;
            printf("There are %d processes running\n", *NUM_PROCESSES_RUNNING);
            (void)childpid;     // suppress "unused variable" warning
        } else {
            printf("Wait what\n");
        }
    } else {
        printf("Oops, bad input\n");
    }
}

Please do disregard the constants being incremented and decremented.

Now, this only works partially. Whenever I give it a command to create another process and run another program (condition action == 0, this has been tested and works), the fork happens and the program is correctly executed.

However, I cannot fork multiple times. What I mean by this is: the program forks and the child executes as instructed in the execv call. The problem is that instead of the parent process then goes back to expecting input to possibly fork again, it waits for the child process to finish.

What I am trying to make this cycle do is for the parent to always be expecting input and forking as commanded, having multiple children if necessary. But as I explained above, the parent gets "stuck" waiting for the single child to finish and only then resumes activity.

Thank you in advance.

Edit: I have experimented multiple combinations of not waiting for the child process, using extra forks to expect input etc.

Upvotes: 1

Views: 4012

Answers (1)

nullp0tr
nullp0tr

Reputation: 485

From man wait.2

The wait() system call suspends execution of the calling process until one of its children terminates.

Your program gets stuck because that's what wait does. Use waitpid instead with WNOHANG.

waitpid(pid_child, &status, WNOHANG);

doesn't suspend execution of the calling process. You can read the waitpid man page to find out the return values and how to know if a child terminated.

Upvotes: 4

Related Questions