Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Problem redirecting a C program output in bash

I've coded a program in C that sends messages to the stdout using printf and I'm having trouble redirecting the output to a file (running from bash).

I've tried:

./program argument >> program.out
./program argument > program.out
./program >> program.out argument
./program > program.out argument

In each case, the file program.out is created but it remains empty. After the execution ends the file size is 0.

If I omit the redirection when executing the program:

./program argument

Then, all messages sent to stdout using printf are shown in the terminal.

I have other C programs for which I've no problem redirecting the output this way. Does it have to do with the program itself? with the argument passing? Where should look for the problem?

Some details about the C program:

  • It does not read anything from stdin
  • It uses BSD Internet Domain sockets
  • It uses POSIX threads
  • It assigns a special handler function for SIGINT signal using sigaction
  • It sends lots of newlines to stdout (for those of you thinking I should flush)

Some code:

int main(int argc, char** argv)
{
    printf("Execution started\n");
    do
    {        
        /* lots of printf here */
    } while (1);
    /* Code never reached */
    pthread_exit(EXIT_SUCCESS);
}
like image 801
mmutilva Avatar asked Feb 01 '09 00:02

mmutilva


2 Answers

Flushing after newlines only works when printing to a terminal, but not necessarily when printing to a file. A quick Google search revealed this page with further information: http://www.pixelbeat.org/programming/stdio_buffering/

See the section titled "Default Buffering modes".

You might have to add some calls to fflush(stdout), after all.

You could also set the buffer size and behavior using setvbuf.

like image 128
gclj5 Avatar answered Sep 21 '22 03:09

gclj5


Flushing the buffers is normally handled by the exit() function, which is usually called implicitly by a return from main(). You are ending your program by raising SIGINT, and apparently the default SIGINT handler does not flush the buffers.

Take a look at this article: Applying Design Patterns to Simplify Signal Handling. The article is mostly C++, but there is a useful C example in the 2nd section, which shows how to use SIGINT to exit your program gracefully.

As for why the behavior of a terminal differs from a file, take a look at Stevens' Advanced Programing in the UNIX Environment Section 5.4 on Buffering. He says that:

Most implementations default to the following types of buffering. Standard error is always unbuffered. All other streams are line buffered if they refer to a terminal device; otherwise, they are fully buffered. The four platforms discussed in this book follow these conventions for standard I/O buffering: standard error is unbuffered, streams open to terminal devices are line buffered, and all other streams are fully buffered.
like image 33
user10892 Avatar answered Sep 21 '22 03:09

user10892