Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Results of printf() and system() are in the wrong order when output is redirected to a file [duplicate]

I have a C program that compiles to an executable called myprogram. This is its main function:

int main(int argc, char ** argv) {   printf("this is a test message.\n");   system("ls");    return 0; } 

When I run myprogram > output.txt in a Linux shell and then examine output.txt, I see the output of ls listed above "this is a test message."

I feel like it should be the other way around. Why is this happening, and what can I do so that "this is a test message" appears at the top of output.txt?

If it matters, I'm new to both C and working in a command line.

like image 599
Archr Avatar asked Sep 27 '18 10:09

Archr


People also ask

What is io redirection?

Input/Output (I/O) redirection in Linux refers to the ability of the Linux operating system that allows us to change the standard input ( stdin ) and standard output ( stdout ) when executing a command on the terminal. By default, the standard input device is your keyboard and the standard output device is your screen.

How many times does fork print?

If the fork() system call was successful, both the parent and child process will run concurrently, and this statement will print twice. If the PPID is 1, it means the parent process terminated before the child process.

What does %% mean in printf?

As % has special meaning in printf type functions, to print the literal %, you type %% to prevent it from being interpreted as starting a conversion fmt.


1 Answers

By default output to stdout is line-buffered when connected to a terminal. That is, the buffer is flushed when it's full or when you add a newline.

However, if stdout is not connected to a terminal, like what happens when you redirect the output from your program to a file, then stdout becomes fully buffered. That means the buffer will be flushed and actually written either when it's full or when explicitly flushed (which happens when the program exits).

This means that the output of a separate process started from your code (like what happens when you call system) will most likely be written first, since the buffer of that process will be flushed when that process ends, which is before your own process.

What happens when using redirection (or pipes for that matter):

  1. Your printf call writes to the stdout buffer.
  2. The system function starts a new process, which writes to its own buffer.
  3. When the external process (started by your system call) exits, its buffer is flushed and written. Your own buffer in your own process, isn't touched.
  4. Your own process ends, and your stdout buffer is flushed and written.

To get the output in the "correct" (or at least expected) order, call fflush before calling system, to explicitly flush stdout, or call setbuf before any output to disable buffering completely.

like image 111
4 revs, 3 users 89% Avatar answered Sep 22 '22 15:09

4 revs, 3 users 89%