简体   繁体   中英

Why does the child process behave differently when exec is supplied an invalid command?

        pid_t pid;
        pid = fork(); //Two processes are made
        const char* ptr = secondlinecopy;
        if (pid > 0 && runBGflag==0) //Parent process. Waits for child termination and prints exit status
        {
            int status;
            if (waitpid(pid, &status, 0) == pid && WIFEXITED(status))
            {
                printf("Exitstatus [");
                for (int i = 0; i < noOfTokens; i++)
                {
                    printf("%s ", commands[i]);
                }
                printf("\b] = %d\n", WEXITSTATUS(status));
            }
        }
        else if (pid == 0)  //Child process. Executes commands and prints error if something unexpected happened
        {
             printf("why does this only print when an invalid command is supplied?");
             if (runBGflag==1) insertElement(getpid(),ptr);
             execvp(commands[0], commands);
             printf ("exec: %s\n", strerror(errno));
             exit(1);
        }

In the code excerpt we see a process creation via fork(). When execvp is supplied a real command, such as "ls" for example, we get the output.

/home/kali/CLionProjects/clash/cmake-build-debug: ls
clash      CMakeCache.txt  cmake_install.cmake  Testing
clash.cbp  CMakeFiles      Makefile
Exitstatus [ls] = 0

However, if we supply an invalid command, the output will be:

/home/kali/CLionProjects/clash/cmake-build-debug: sd
why does this only print when an invalid command is supplied?exec: No such file or directory
Exitstatus [sd] = 1

Why is that the case? Shouldnt the process always call printf("Why does...") first and then run exec?

Why is that the case? Shouldnt the process always call printf("Why does...") first and then run exec?

Let's say it works like this:

printf(...) --> internal buffer --(fflush? newline? max_buffer_size?)--> output

Usually stdout is line buffered and your printf has no newline. The data to-be-printed are stored inside some internal buffer. When exec -ing the stdout is not fflush ed and the parent process is replaced by child process as it is as a whole - so all the data stored in parent process, including some internal stdout state, are removed. When exec fails, stdout is flushed when you printf(...\n" (or after calling exit() when stdout is block buffered) and the data show up. Research: studio buffering modes and setvbuf() function .

Why is that the case? Shouldnt the process always call printf("Why does...") first and then run exec?

Yes, it should, and you've not presented any reason to think that it doesn't.

printf directs output to the standard output stream, and that defaults to being line buffered when it is connected to an interactive device, or to being block buffered otherwise. When execvp() succeeds, it replaces the whole program image with that of a new program, including the contents of any I/O buffers. Any data that have been buffered but not flushed to the underlying device are lost.

When execvp() fails and the program thereafter terminates normally (regardless of its exit status) all then-buffered buffered data is automatically flushed to the relevant output device.

You would see different behavior if you appended a newline to the message you are printing, or if you called fflush(stdout) between the printf and execvp calls, or if you printed to stderr instead of to stdout , or if you turned off buffering of stdout .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM