Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

When std::fprintf(stderr,...) fails, does the operation has no effect or can write a little before fail?

Tags:

c++

printf

c++11

I have a C++11 program that uses std::fprintf to write to stderr as a log and debug info. I know fprintf can fail and return a negative value, but I can't found if the operation is atomic (if fails, has no effect) or it can write some part of the text and then fails (or any other side effect).

The function that uses fprintf looks like this:

void writeToConsole (std::string const &message)
{
    std::fprintf(stderr, "%s\n", message.c_str());
}

I am developing using Clang and GCC on Linux (for now), but my question is more about the standard, so...

Question:

If std::fprintf fails, is still possible that some characters had been written to stderr? Is this behaviour a C/C++ standard or is implementation-defined?

Even more, if std::fprintf fails, should I abort the program or can continue execution silently without side effects (other than impossibility of write to stderr)?

like image 301
Daniel Avatar asked Jan 02 '15 02:01

Daniel


2 Answers

Keep in mind that the printf family of functions (almost always) eventually turns into a write(2) function call (or other such low-level, OS/implementation-provided equivalent). This function can be partially successful. If at least one byte is written, the function succeeds (if no error from the underlying destination can be detected - for example, interruption by a signal handler) and it will return the number of bytes actually written:

The number of bytes written may be less than count if, for example, there is insufficient space on the underlying physical medium, or the RLIMIT_FSIZE resource limit is encountered (see setrlimit(2)), or the call was interrupted by a signal handler after having written less than count bytes. [...]

For information about partial writes, see write(2), for example at http://man7.org/linux/man-pages/man2/write.2.html. Values for errno or other effects of a partial write may be dependent on the output medium (or what the file descriptor represents - memory mapped file, regular file, etc.), as well as the specific reason for failure. For example, ENOMEM, EIO, EDQUOT are all possibilities.

Also see the linked man page for additional information about atomicity with regard to multiple threads.

Your other question:

Even more, if std::printf fails, should I abort the program or can continue execution silently without side effects (other than impossibility of write to stderr)?

This really depends on your program.

like image 107
frasnian Avatar answered Oct 12 '22 22:10

frasnian


For fprintf the C++11 standard falls back to C99 since it is part of the C standard library and the C99 draft standard says the following:

The fprintf function returns the number of characters transmitted, or a negative value if an output or encoding error occurred.

but does not actually specify whether an error means no character were transmitted or not, so that will end up dependent on the implementation.

For POSIX compliant systems, which in this case should cover Linux, the reference for fprintf says:

Upon successful completion, the fprintf() and printf() functions shall return the number of bytes transmitted.

[...]

If an output error was encountered, these functions shall return a negative value.

There are several errors listed that could lead to partial output such as:

[ENOMEM]

Insufficient storage space is available.

Whether an error indicates that you should exit your application depends on your application, do you have an alternate logging mechanism other than stderr? Does your application have legal requirements that mandate everything is logged or are the logs purely informational, etc...

like image 20
Shafik Yaghmour Avatar answered Oct 12 '22 22:10

Shafik Yaghmour