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 forkn"); } else if (pid == 0) { (*NUM_PROCESSES_RUNNING)++; printf("There are %d processes runningn", *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 busyn"); continue; } int status, childpid; wait(&status); childpid = WEXITSTATUS(status); (*NUM_PROCESSES_RUNNING)--; printf("There are %d processes runningn", *NUM_PROCESSES_RUNNING); (void)childpid; // suppress "unused variable" warning } else { printf("Wait whatn"); } } else { printf("Oops, bad inputn"); } }
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.
Advertisement
Answer
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.