OS: Windows 11, WSL
Cp: GCC 11.4.0
HW: Intel
I have an example which I have pulled from a shell program. I am attempting to execute a number of programs 'delimited' by an &. Given a fixed array of strings which are valid bash, command arguments separated by an '&', I should be able to fork and execute all separate program calls in parallel. Unfortunately, I am running into an exit status of 0x3 (cannot open path specified) when forking. I'm unsure where this comes from or why.
Below is a far simplified version of my original program. First, the program array is built, then it is passed to the 'execute_programs' function which will fork and execute each new valid call. The call to 'execv' can be ignored, but I left it to show the a complete picture. In this example, only one fork occurs. I receive the output,
Child with PID -1 exited with status 0x3.
I do not understand why this would occur. There may be other errors, but this result is entirely unexpected and elusive to me. I would appreciate some help.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
#include <sys/wait.h>
int execute_programs(int argc, char *argv[])
{
int n = 0;
int cnt = 0;
int current_cnt = 0;
while (argv[cnt] != NULL && cnt < argc)
{
if (strcmp(argv[cnt], "&") == 0)
{
// Block the array.
argv[cnt] = NULL;
// Update variables.
n++; // Number of programs grows.
current_cnt = 0; // Number of current arguments goes back to zero.
if (current_cnt > 0) // There is an adequate number of child processes.
{
// Start child process.
pid_t rc;
if ((rc = fork()) < 0)
{
// There was an error.
abort();
}
else if (rc == 0)
{
// Run the i'th process.
// printf("%d\n", execv(argv[cnt - current_cnt], &argv[cnt]));
exit(0);
}
}
}
current_cnt++; // Increment number of current arguments.
cnt++; // Increment count;
}
/* Wait for children to exit. */
int status;
pid_t pid;
while (n > 0)
{
pid = wait(&status);
printf("Child with PID %ld exited with status 0x%x.\n", (long)pid, status);
--n;
}
// return;
return 0;
}
int main(int argc, char *argv[])
{
char *programs[5];
programs[0] = strdup("echo");
programs[1] = strdup("\"ah\"");
programs[2] = strdup("&");
programs[3] = strdup("ls");
programs[4] = NULL;
execute_programs(5, programs);
return 0;
}
Edit: The 'execv' call is commented out because I may not be using it correctly. Nonetheless, the error occurs without it. The same error message is given.
Your code has a bug. You're assigning current_cnt
to 0, which results in fork()
and execv()
can NOT be reached. It seems to me that current_cnt = 0;
should be moved to the end of if
clause.
current_cnt = 0;
if (current_cnt > 0) // can NOT reach below
{
// Start child process.
pid_t rc;
if ((rc = fork()) < 0) {
// There was an error.
abort();
} else if (rc == 0) {
// Run the i'th process.
printf("%d\n", execv(argv[cnt - current_cnt], &argv[cnt]));
exit(0);
}
}
wait()
returns (pid_t)(-1)
if it fails and you can check errno
for detailed reason. I test your code in WSL, and errno
stated that spawning child process was failed.
#include <errno.h>
pid = wait(&status);
int err = errno;
printf("Error: %s\n", strerror(err)); // Error: No child processes