Search code examples
coutputprintfstdoutexecvp

Why am I not seeing the printf buffer flush?


I have a simple program (working example):

#include <unistd.h>
#include <stdio.h>

int main() {
  pid_t my_pid = getpid();
  char str[30];

  sprintf(str, "/proc/%d/fd", my_pid);
  printf("hello, I am gonna print out: %s", str);

  execvp( "ls", (char *[]) { "ls", str, NULL } );

  return 0;
}

compiled with gcc on a Linux VM. My question is why the output sent to printf is never printing.

I understand that printf buffers its output and only flushes on \n. I am wondering why it is that it doesn't print in this case. I read that output streams are flushed on program exit. printf is buffering outputs in a malloc'd piece of memory (I confirmed this in my implementation).

My questions about this (more details are welcome):

  • Why does commenting out the call to execvp cause the output to be printed on stdout, but it is not printed as is? My thought is, wouldn't it still be considered program exit even after ls cannibalizes the process?
  • Would printf's in-memory buffer be considered an output stream?
  • A completely unrelated detail to this question is I am wondering why the file descriptor 10 on zsh and 255 on bash are not inherited by my process.

Solution

  • execvp replaces the old process with a new process. Any open file descriptors remain open, but the data buffered by the C stdio library is not preserved. The C startup code will attach a new FILE pointer to the STDOUT file descriptor. The key point is that a file descriptor is an OS object, whereas a FILE pointer is a C library object. Only the OS object is preserved.