Reputation: 11
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?
Upvotes: 0
Views: 30
Reputation: 181459
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
.
Upvotes: 0
Reputation: 141768
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.
Upvotes: 1