1

I'm having an issue with a process being stuck on wait. I've been troubleshooting this issue and its the only bug i have currently for my shell program.

The problem is the program should exit when the user enters "exit". However it seems if the user enters an invalid string the program gets stuck on wait(). this results in having to type exit twice to exit instead of once. How do I stop this from happening, how do i exit from the wait() call when a user enters a dumb string?

Steps to reproduce:

  • compile and run with gcc/g++
  • type in an expletive of your choice
  • type exit
  • notice the program doesnt exit (because its stuck on wait() but prompting
  • type exit again
  • program exits


#include <iostream>
#include <unistd.h>
#include "stdlib.h"
#include "stdio.h"
#include <iostream>
#include <string>
#include <sys/wait.h>
#include <sstream>
#include <cstring>
#include <sys/types.h>
#include <sys/stat.h>

using std::string;

using std::cout;
using std::endl;


bool exitstatus;
int argsIndex = 0;
pid_t pid;
int main(void)
{  

    char * args[100];
    string check = "";           

    while(exitstatus==false)
    {
        cout<<"tinyshell:~>";
        std::getline(std::cin, check);
        if(check == "exit"){
            exitstatus==true;

        }

        if(exitstatus==false&&check!="cd..")
        {
            pid = fork();
            perror("");
            if (pid < 0) { /* error occurred */
                fprintf(stderr, "Fork Failed");
                //return 1;
            }
            else if (pid == 0 ) { /* child process */
                execvp(args[0],args);
                perror("");
            }
            else if(check!= "&"){/* parent will wait for the child to complete */
                wait(NULL);
                perror("");
                //  cout <<"Child Complete" << endl;
            }
            else
            {
            }
        }
    }
    return 0;
};
Mars01
  • 79
  • 2
  • 10
  • You do `fork()` so you may have more than one process to terminate. And the child process inherits `exitstatus` value `false` at the `fork()` time, so it needs separate closing. Try adding `getpid()` result to the "tinyshell" prompt to see which process you are talking to. – CiaPan Feb 25 '15 at 08:15

1 Answers1

0

It may have to do something with this line:

exitstatus==true;

Did you, by any chance meant:

existatus = true;

gcc reports something like this for it anyway (-Wall):

warning: statement has no effect [-Wunused-value]
         exitstatus==true;

That's a pretty nice example showing why enabling warnings is a good practice ...

There's also a more subtle problem with your code. You're not checking the result of your execvp function. So basically if you enter some garbage command in your shell your exec will fail but your child process will continue running the same code as the parent (the loop).

Just add an exit(EXIT_FAILURE); after your execvp() call.

dragosht
  • 3,237
  • 2
  • 23
  • 32
  • yes I saw that warning on compile and its unrelated, this is reproducing the same issue im having in the full program that compiles with no warnings. it is obviously used since the program exits under that condition though no? I may be misunderstanding what you are trying to say here – Mars01 Feb 25 '15 at 07:53
  • When you do the `fork()` you already have a child tinyshell process. If `execvp` fails you get a parent shell process and a child shell process that run the same thing and the parent waiting for the child. `exit` just makes sure you end the child preventing all that ... – dragosht Feb 25 '15 at 08:26
  • Ah, I see. Thanks so much. So, when Im calling exec(), it IS actually considered to be failing when it outputs "no such directory or file"? I'm not clear on that aspect, i thought it would be more explicit. Also to clarify, the exit call following exec is just exiting the child process correct? – Mars01 Feb 25 '15 at 08:32
  • @Mars01 `exec` is locating the executable given as argument, wipes out the whole current process' image with that and starts executing it. It's a function that cannot/should not return. The only way it can return is after a failure - hence `exit(EXIT_FAILURE);` ... – dragosht Feb 25 '15 at 08:35
  • Thanks again I really appreciate the help and input. To clarify, the exit call is being called in the child process, so its killing the child and not the parent correct? – Mars01 Feb 25 '15 at 08:39
  • You were previously spawning a tinishell within your tinyshell. So yes ... you were then supposed to kill the first via `exit()` in order to return to the first one. – dragosht Feb 25 '15 at 08:54
  • so the reason for the double exit was that one was exiting the child, the other exiting the parent then yes? Yes i did accept this answer even before i read your comment. – Mars01 Feb 25 '15 at 09:07
  • Yes. You were initially exiting the child process, return to your parent process right after the `wait` and resume that command reading loop. – dragosht Feb 25 '15 at 09:17