printf flush at program exit - c

I'm interested in knowing how the printf() function's flush works when the program exits.
Let's take the following code:
int main(int ac, char **av)
{
printf("Hi");
return 0;
}
In this case, how does printf() manage to flush its buffer to stdout?
I guess it's platform dependent, so let's take Linux.
It could be implemented using gcc's __attribute__((dtor)) but then the standard library would be compiler dependent. I assume this is not the way it works.
Any explanations or links to documentation is appreciated. Thank you.

The C runtime will register atexit() handlers to flush standard buffers when exit() is called.
See this explanation.

When the program exits normally, the exit function has always performed a clean shutdown of the standard I/O library, this causes all buffered output data to be flushed.
Returning an integer value from the main function is equivalent to calling exit with the same value.So, return 0 has the same effect with exit(0)
If _Exit or _exit was called, the process will be terminated immediately, the IO won't be flushed.

Just to expand trofanjoe's response:
exit causes normal program termination. atexit functions are called in
reverse order of registration, open files are flushed, open streams
are closed, and control is returned to the environment.
and
Within main, return expr is equivalent to exit(expr). exit has the
advantage that it can be called from other functions

From man stdio on my machine here (emphasis added), whic runs RHEL 5.8:
A file may be subsequently reopened, by the same or another
program execution, and its contents reclaimed or modified (if it can
be repositioned at the start). If the main function returns to its
original caller, or the exit(3) function is called, all open files are
closed (hence all output streams are flushed) before program
termination. Other methods of program termination, such as abort(3)
do not bother about closing files properly.

Related

How to make sure file is closed in C program with exit() used

I am maintaining c project where the program can be simplified as follows:
int main(int argc, const char* argv[]) {
initVM();
// global pointer to a file where all output of
// the program are directed to
debugOut = fopen(DEBUG_OUTPUT_FILE_PATH, "wt");
if (argc == 2) runFile(argv[1]); // may call `exit`
else if (argc == 1) repl(); // may call `exit`
else {
fprintf(stderr, "Usage: clox [path]\n");
exit(64);
}
fclose(debugOut);
freeVM();
return 0;
}
The question is: what if exit function was called before fclose, will the file be closed?
I think the answer is no, if so, how to make sure the file is closed? define my own exit function and use it whenever I need to terminate the program?
Alas, there is no finally statement in c. Or there is?
Since I haven't mastered c yet, I went online searching for what exit function does or finally statement equivalents in c. I came here to post the question and I am still searching for it.
The ISO C standard states that open streams will be closed.
C23 §7.24.4.4 The exit function
The exit function causes normal program termination to occur. No functions registered by the at_quick_exit function are called. If a program calls the exit function more than once, or calls the quick_exit function in addition to the exit function, the behavior is undefined.
First, all functions registered by the atexit function are called, in the reverse order of their registration, except that a function is called after any previously registered functions that had already been called at the time it was registered. If, during the call to any such function, a call to the longjmp function is made that would terminate the call to the registered function, the behavior is undefined.
Next, all open streams with unwritten buffered data are flushed, all open streams are closed, and all files created by the tmpfile function are removed.
Finally, control is returned to the host environment. If the value of status is zero or EXIT_SUCCESS, an implementation-defined form of the status successful termination is returned. If the value of status is EXIT_FAILURE, an implementation-defined form of the status unsuccessful termination is returned. Otherwise the status returned is implementation-defined.
From this description we also learn about the atexit function, which can be used to register functions to be called upon normal program termination (calling exit or returning from main).
You may also consider restructuring your code so that the correctness of the program arguments is validated before opening any streams.
Yes, the file will be closed. Any open file descriptors are closed automatically when exit is used in C. However, it is good practice to close the file descriptors yourself, so you can check that they have been closed successfully.

Is it possible to change the exit code in a function registered with atexit()?

The man page for atexit(3) says the following:
POSIX.1-2001 says that the result of calling exit(3) more than once (i.e., calling exit(3) within a function registered using atexit()) is undefined. On some systems (but not Linux), this can result in an infinite recursion; portable programs should not invoke exit(3) inside a function registered using atexit().
However, I'm interested in modifying the exit code in a finalizer for my program. The only way I've managed to do this is by calling exit() from within my finalization function, but the man page explicitly warns against that.
Is there any practical danger against doing this? Are there any implementations where that approach might cause problems? Even better, is there another way of doing this?
You can call _exit() instead.
Within the Notes section of the man page:
The function _exit() is like exit(), but does not call any functions registered with atexit() or on_exit().
This should avoid the "recursive" issue that is being warned about in the POSIX spec. If you are somehow able to guarantee that your "exit code changing" exit handler runs last, this should work perfectly, modulo the caveats also listed in the Notes:
Whether it flushes standard I/O buffers and removes temporary files created with tmpfile(3) is implementation-dependent. On the other hand, _exit() does close open file descriptors, and this may cause an unknown delay, waiting for pending output to finish. If the delay is undesired, it may be useful to call functions like tcflush(3) before calling _exit(). Whether any pending I/O is canceled, and which pending I/O may be canceled upon _exit(), is implementation-dependent.

weird output when I use pthread and printf

I write a program using pthread.
Environment:windows 7 , CYGWIN_NT-6.1 i686 Cygwin , gcc (GCC) 4.5.3
The source code
#include<stdio.h>
#include<pthread.h>
void *th_func(void *p)
{
int iLoop = 0;
for(iLoop = 0;iLoop<100;iLoop++)
{
printf("Thread Thread Thread Thread\n");
}
return;
}
int main()
{
int iLoop = 0;
pthread_t QueThread;
printf("Main : Start Main\n");
printf("Main : Start Create Thread\n");
pthread_create(&QueThread,NULL,th_func,NULL);
printf("Main : End Create Thread\n");
for(iLoop = 0;iLoop<100;iLoop++)
{
printf("Main Main Main Main\n");
}
pthread_join(QueThread,NULL);
printf("Main : End Main\n");
printf("---------------\n");
return 0;
}
When I compile the source code, there are no warnings or errors,but it's output is weird.
A part of it's output
Main : Start Main
Main : Start Create Thread
Thread Thread Thread ThreThread Thread Thread Thread
Main Main Main Main
Thread Thread Thread Thread
Main Main Main Main
I want to know the cause of such phenomenon.
In this output, Main : End Create Thread is not printed completely. And at line 3, a newline \n at the end of "Thread Thread Thread Thread\n" disappear.
Is everyone's output like this? It does not occur every time, but occurs sometime.
If I use mutex to call printf safely,the weird output seem to be stopped.
POSIX says printf is thread-safe, and according to Cygwin.com, cygwin provides posix-style API. However, there is the unexpected output.
Is printf really thread-safe?
I executed the same program 100 times in Linux(Ubuntu), and this output did not occur.
In addition, I have not understood the reason why some words on the output disappeared.
This looks like it may be a bug in Cygwin, or maybe something is misconfigured. Several answer here indicate that 'thread safe' only promises that the function won't cause harm to the program, and that thread safety doesn't necessarily mean that a function is 'atomic'. But, as far as I know, POSIX doesn't formally define 'thread safe' (if anyone has a pointer to such a definition, please post it in a comment).
However, not only does POSIX specify that printf() is thread safe, POSIX also specifies that:
All functions that reference ( FILE *) objects shall behave as if they use flockfile() and funlockfile() internally to obtain ownership of these ( FILE *) objects.
Since printf() implicitly references the stdout FILE* object, all printf() calls should be atomic with respect to each other (and any other function that uses stdout).
Note that this might not be true on other systems, but in my experience it does hold true for many multi threaded systems.
The POSIX standard has functions like putc_unlocked() where the commentary says:
Versions of the functions getc(), getchar(), putc(), and putchar() respectively named getc_unlocked(), getchar_unlocked(), putc_unlocked(), and putchar_unlocked() shall be provided which are functionally equivalent to the original versions, with the exception that they are not required to be implemented in a thread-safe manner. They may only safely be used within a scope protected by flockfile() (or ftrylockfile()) and funlockfile(). These functions may safely be used in a multi-threaded program if and only if they are called while the invoking thread owns the (FILE *) object, as is the case after a successful call to the flockfile() or ftrylockfile() functions.
That clearly indicates that the low-level functions for single character I/O are normally thread-safe. However, it also indicates that the level of granularity is a single character output operation. The specification for printf() says:
Characters generated by fprintf() and printf() are printed as if fputc() had been called.
And for putc(), it says:
The putc() function shall be equivalent to fputc(), except that if it is implemented as a macro it may evaluate stream more than once, so the argument should never be an expression with side-effects.
The page for fputc() doesn't say anything about thread-safety, so you have to look elsewhere for that information.
Another section describes threads and says:
All functions defined by this volume of POSIX.1-2008 shall be thread-safe, except that the following functions need not be thread-safe.
And the list following includes the *_unlocked() functions.
So, printf() and fputc() have to be thread-safe, but the writing by printf() is done 'as if' by fputc(), so the interleaving of output between threads may be at the character level, which is more or less consistent with what you see. If you want to make calls to printf() non-interleaved, you would need to use the flockfile() and funlockfile() calls to give your thread ownership of stdout while the printf() is executed. Similarly for fprintf(). You could write an fprintf_locked() function quite easily to achieve this result:
int fprintf_locked(FILE *fp, const char *format, ...)
{
flockfile(fp);
va_list args;
va_start(args, format);
int rc = vfprintf(fp, format, args);
va_end(args);
funlockfile(fp);
return rc;
}
You could insert a fflush(fp) in there if you wished. You could also have a vfprintf_locked() and have the function above call that to do the lock, format, (flush) and unlock operations. It's probably how I'd code it, trusting the compiler to inline the code if that was appropriate and doable. Supporting the versions using stdout is likewise pretty straight-forward.
Note the fragment of POSIX specification for flockfile() quoted by Michael Burr in his answer:
All functions that reference (FILE *) objects, except those with names ending in _unlocked, shall behave as if they use flockfile() and funlockfile() internally to obtain ownership of these (FILE *) objects.
Apart from the odd parentheses around the FILE *, these lines impact all the other standard I/O functions, but you have to know that these lines exist in one of the less frequently used man pages. Thus, my fprintf_locked() function should be unnecessary. If you find an aberrant implementation of fprintf() that does not lock the file, then the fprintf_locked() function could be used instead, but it should only be done under protest — the library should be doing that for you anyway.
Just because a function is thread-safe, it doesn't mean it's atomic.
In your case, if you want to ensure that your output don't get interleaved, you need to use a mutex to ensure that only one thread calls printf at a time.
Threads behave like this for a reason. If threads were executed one after another and not 'at the same time' (in an interleaved manner), there would be no point in this kind of 'concurrency'. When you use mutexes, the threads will be blocked according to your intention, and they generate the expected output.
Also, you write return; in a function that returns void * and that is undefined behavior, so anything can happen when running your program.
I will put this in a simple way you have two threads which are trying to access a resource. And also there is no kinds priority checks or anything like a mutex. Theoretically, threads without mutex or priority gets assigned with resources randomly. try creating two threads with one thread printing yes and the other one printing no. you will find this unusual behavior. Also remember running time is different for different threads in this case. If you try the same stuff with one thread writing the info to a file and other guy writing to console. You will not encounter such an issue. Hope that helps....

Standard streams and vfork

I am playing a bit with fork/vfork functions, and there is something that is puzzling to me. In Stevens book it is written that:
Note in Figure 8.3 that we call _exit instead of exit.
As we described in Section 7.3, _exit does not perform any flushing of standard I/O buffers. If we call exit instead, the results are indeterminate.
Depending on the implementation of the standard I/O library, we might see no difference in the output, or we might find that the output from the parent's printf has disappeared.
If the child calls exit, the implementation flushes the standard I/O streams.
If this is the only action taken by the library, then we will see no difference with the output generated if the child called _exit.
If the implementation also closes the standard I/O streams, however, the memory representing the FILE object for the standard output will be cleared out.
Because the child is borrowing the parent's address space, when the parent resumes and calls printf, no output will appear and printf will return -1.
Note that the parent's STDOUT_FILENO is still valid, as the child gets a copy of the parent's file descriptor array (refer back to Figure 8.2).
Most modern implementations of exit will not bother to close the streams.
Because the process is about to exit, the kernel will close all the file descriptors open in the process.
Closing them in the library simply adds overhead without any benefit.
so I tried to test if I can get printf error, in my manual of vfork there is:
All open stdio(3) streams are flushed and closed. Files created by tmpfile(3) are removed.
but when I compile and execute this program:
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/wait.h>
int main()
{
int s;
pid_t ret;
if (vfork() == 0)
{
//abort();
exit(6);
}
else
{
ret=wait(&s);
printf("termination status to %d\n",s);
if (WIFEXITED(s))
printf("normalnie, status to %d\n",WEXITSTATUS(s));
}
return 0;
}
everything is working fine, I don't get any printf errors. Why is that?
The end of the paragraph you quoted says:
Most modern implementations of exit will not bother to close the streams. Because the process is about to exit, the kernel will close all the file descriptors open in the process. Closing them in the library simply adds overhead without any benefit.
This is most likely what's happening. Your OS doesn't actually close the stream (but it does probably flush it).
The important thing isn't what exit does here, its the underlying concept. The child is sharing the parent's memory and stack frame. That means that the child can very easily change something that the parent did not expect, which could easily cause the parent to crash or misbehave when it starts running again. The man page for vfork says the only thing a process can do is call exit() or an exec. In fact, the child should not even allocate memory or modify any variables.
To see the impact of this, try putting the vfork call inside of a function and let the child return or modify some variables there and see what happens.

What happens if I don't call fclose() in a C program?

Firstly, I'm aware that opening a file with fopen() and not closing it is horribly irresponsible, and bad form. This is just sheer curiosity, so please humour me :)
I know that if a C program opens a bunch of files and never closes any of them, eventually fopen() will start failing. Are there any other side effects that could cause problems outside the code itself? For instance, if I have a program that opens one file, and then exits without closing it, could that cause a problem for the person running the program? Would such a program leak anything (memory, file handles)? Could there be problems accessing that file again once the program had finished? What would happen if the program was run many times in succession?
As long as your program is running, if you keep opening files without closing them, the most likely result is that you will run out of file descriptors/handles available for your process, and attempting to open more files will fail eventually. On Windows, this can also prevent other processes from opening or deleting the files you have open, since by default, files are opened in an exclusive sharing mode that prevents other processes from opening them.
Once your program exits, the operating system will clean up after you. It will close any files you left open when it terminates your process, and perform any other cleanup that is necessary (e.g. if a file was marked delete-on-close, it will delete the file then; note that that sort of thing is platform-specific).
However, another issue to be careful of is buffered data. Most file streams buffer data in memory before writing it out to disk. If you're using FILE* streams from the stdio library, then there are two possibilities:
Your program exited normally, either by calling the exit(3) function, or by returning from main (which implicitly calls exit(3)).
Your program exited abnormally; this can be via calling abort(3) or _Exit(3), dying from a signal/exception, etc.
If your program exited normally, the C runtime will take care of flushing any buffered streams that were open. So, if you had buffered data written to a FILE* that wasn't flushed, it will be flushed on normal exit.
Conversely, if your program exited abnormally, any buffered data will not be flushed. The OS just says "oh dear me, you left a file descriptor open, I better close that for you" when the process terminates; it has no idea there's some random data lying somewhere in memory that the program intended to write to disk but did not. So be careful about that.
The C standard says that calling exit (or, equivalently, returning from main) causes all open FILE objects to be closed as-if by fclose. So this is perfectly fine, except that you forfeit the opportunity to detect write errors.
EDIT: There is no such guarantee for abnormal termination (abort, a failed assert, receipt of a signal whose default behavior is to abnormally terminate the program -- note that there aren't necessarily any such signals -- and other implementation-defined means). As others have said, modern operating systems will clean up all externally visible resources, such as open OS-level file handles, regardless; however, FILEs are likely not to be flushed in that case.
There certainly have been OSes that did not clean up externally visible resources on abnormal termination; it tends to go along with not enforcing hard privilege boundaries between "kernel" and "user" code and/or between distinct user space "processes", simply because if you don't have those boundaries it may not be possible to do so safely in all cases. (Consider, for instance, what happens if you write garbage over the open-file table in MS-DOS, as you are perfectly able to do.)
Assuming you exit under control, using the exit() system call or returning from main(), then the open file streams are closed after flushing. The C Standard (and POSIX) mandate this.
If you exit out of control (core dump, SIGKILL) etc, or if you use _exit() or _Exit(), then the open file streams are not flushed (but the file descriptors end up closed, assuming a POSIX-like system with file descriptors - Standard C does not mandate file descriptors). Note that _Exit() is mandated by the C99 standard, but _exit() is mandated by POSIX (but they behave the same on POSIX systems). Note that file descriptors are separate from file streams. See the discussion of 'Consequences of Program Termination' on the POSIX page for _exit() to see what happens when a program terminates under Unix.
When the process dies, most modern operating systems (the kernel specifically) will free all of your handles and allocated memory.

Resources