cforksystem-callserror-code

Executing fork call gives exit status 0x3 for Linux


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.


Solution

  • 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