Search code examples
cbashoutputforkparents

Process Hangs in Parent Process in C


I have a program that seems to be hanging in the parent process. It's a mock bash program that accepts commands like bash, and then operates them. The code is below. (Note this is simplified code without error checking so it would be more easily readable. Assume its all properly nested inside main function)

#define MAX_LINE 80

char *args[MAX_LINE/2 + 1];
while(should_run){
    char *inputLine = malloc(MAX_LINE);
    runConcurrently = 0; /*Resets the run in background to be line specific */

    fprintf(stdout, "osh> "); /*Command prompt austhetic */
    fflush(stdout);

   /*User Input */
   fgets(inputLine, MAX_LINE, stdin); 

   /*Reads into Args array */
   char *token = strtok(inputLine, " \n");
    int spot = 0;
    while (token){
        args[spot] = token;
        token = strtok(NULL, " \n");
        spot++;
    }
    args[spot] = NULL;

    /* checks for & and changes flag */   
    if (strcmp(args[spot-1], "&") == 0){
            runConcurrently = 1;
            args[spot-1] = NULL;
    }


    /* Child-Parent Fork Process */
    pid_t pid; 
    pid = fork(); /*Creates the fork */
    if (pid == 0){
        int run = execvp(args[0], args);
        if (run < 0){
            fprintf(stdout, "Commands Failed, check syntax!\n");
            exit(1);
        }
    }
    else if (pid > 0) {
        if (!runConcurrently){
            wait(NULL);
        }
    }
    else {
        fprintf(stderr, "Fork Failed \n");
        return 1;
    }
}

The problem here has to do with when I use an '&' and activate the run concurrently flag. This makes it so the parent no longer has to wait, however when I do this I lose some functionality.

Expected output:

osh> ls-a &
//Outputs a list of all in current directory
osh> 

So I want it to run them concurently, but give control of the terminal back to me. But instead I get this.

Actual Result:

osh> ls -a &
//Outputs a list of all in current directory
     <---- Starts a new line without the osh>. And stays like this indefinitely

And if I type something into this blank area the result is:

osh> ls -a &
//Outputs a list of all in current directory
ls -a 
//Outputs a list of all in current directory
osh> osh> //I get two osh>'s this time. 

This is my first time working with split processes and fork(). Am I missing something here? When I run it concurrently should I be choosing processes or something like that? Any help is welcome, thanks!


Solution

  • Your code actually works fine. The only problem is, you spit out the prompt "too quickly", and the new prompt appears before the command output. See a test output here:

    osh> ls -al &
    osh> total 1944    --- LOOK HERE
    drwxrwxrwt 15 root root       4096 Feb 15 14:34 .
    drwxr-xr-x 24 root root       4096 Feb  3 02:13 ..
    drwx------  2 test test       4096 Feb 15 09:30 .com.google.Chrome.5raKDW
    drwx------  2 test test       4096 Feb 15 13:35 .com.google.Chrome.ueibHT
    drwx------  2 test test       4096 Feb 14 12:15 .com.google.Chrome.ypZmNA
    

    See the "LOOK HERE" line. The new prompt is there, but ls command output appears later. Your application is responsive to new commands, even though the prompt is displayed before command output. You can verify all this by using a command that does not produce any output, for example

    osh> sleep 10 &
    

    Hannu