0

I was asked to simulate the Unix shell in C, and the part of code is following:

    int  pid, argc=0;
    should_wait=0;

    argc = makeargv(buffer,args);

    if(argc!=0)
    if(strcmp(args[argc-1],"&")==0){
            args[argc-1]=NULL;
            should_wait=1;
            }

    if(argc!=0)
    if((pid=fork())==0){
            execvp(args[0],&args[0]);
            exit(1);
    }

    if(should_wait){
            printf("parent here\n");
            wait(NULL);
            printf("Child complete\n");
    }

The parent process suppose to wait for the child if input arguments following by & for example: parent wait child enter ls &, parent does not wait child enter `ls. However, the output is:



osh>ls &
parent here
Child complete
osh>a.out
argv.c myshell.c
|

CinCout
  • 9,486
  • 12
  • 49
  • 67
Ming
  • 9
  • 1
  • 2
  • 3
    Actually, normally it's the opposite - the `&` at the end specifies that the job should run in background (i.e. the shell doesn't wait before giving you the prompt back). – Matteo Italia Oct 01 '15 at 05:17
  • 1
    @Ashik: he needs to wait for the child process to terminate, not for some amount of time. Delay has no place here. – Matteo Italia Oct 01 '15 at 05:20
  • Examine return value of `wait`! Also might be useful to check if `execvp` actually succeeded, and print error message instead of just `exit(1)` if it fails. Also, wouldn't hurt to check if `fork` fails, too. – hyde Oct 01 '15 at 05:41
  • Additionally, I would strongly suggest you use `{}` around every nested block. Too easy to make mistakes if you are "lazy" and leave it out, especially when you're learning. But at least indent your code properly. – hyde Oct 01 '15 at 05:42
  • any specific need to pass NULL to wait? – incompetent Oct 01 '15 at 07:45
  • @shami and Ming, read man page of `wait`... Passing NULL is the first thing to change when there are problems, so you can get the status back from it and examine what's going on... Link: http://linux.die.net/man/2/wait – hyde Oct 01 '15 at 11:11

1 Answers1

-3

AS from comments it is clear that exec replaces the memory of process with new image then you have no way to wait for child after exec. The reason for my rationale is that execvp does not return if it is successful. Instead use system() you can get status of child. Just check the return value of the wait() it must be -1.

incompetent
  • 1,715
  • 18
  • 29
  • If exec detached, then how could you create a child process at all, other than clones of current process? – hyde Oct 01 '15 at 06:50
  • you dont call any exec it will be child :) you can perform different things in child also but if you want to execute new program then it will not be child of spawning process – incompetent Oct 01 '15 at 06:53
  • 2
    @shami `exec` has nothing to do with parent/child relationships of processes. It loads a new program into the current process, and starts executing that program. – user253751 Oct 01 '15 at 06:58
  • @shami Still wrong I think. Why can't you wait for the child process after it execs? – user253751 Oct 01 '15 at 07:57
  • bcz exec does not return. My previous wrong understanding was also due to this same problem (of wait not waiting) which we faced in one of our class project. – incompetent Oct 01 '15 at 08:01
  • 1
    How do you think `system` is implemented? It's "fork,exec,wait". – Art Oct 01 '15 at 08:01
  • @Art I am afraid I dont know the internals of system but we solved the same problem with system() and passing reference in wait() – incompetent Oct 01 '15 at 08:05
  • I am curious to know the reason of" wait() not waiting" other than that execvp does not return – incompetent Oct 01 '15 at 08:08
  • @shami We don't know why `wait()` does not wait for the question code, because OP doesn't examine and print its return value, or the relevant pids. – hyde Oct 01 '15 at 11:09
  • Thank you all for answering my question. Actually, I have solved my problem by double "wait(NULL);" in the if(should_wait) function. However, I don't understand how does it works... – Ming Oct 02 '15 at 13:53
  • by double wait(NULL) means you used two times wait?? – incompetent Oct 02 '15 at 14:19
  • @Ming print return value of every `fork` call, and every `wait` call you do. That might help you understand what is happening (we don't know, not enough details in the question). – hyde Oct 04 '15 at 07:12