Error checking fprintf when printing to stderr

According to the docs, fprintf may fail and return a negative number on error. There are many situations where it would be useful to verify this value.

However, I usually use fprintf to print error messages in stderr. My code would look something like this:

rc = foo(); if(rc) { fprintf(stderr, "An error occured\n"); //Sometimes stuff will need to be cleaned up here return 1; } 

In these cases, is it possible for fprintf to fail? If so, is there anything that can be done to display the error message, or is there a more robust alternative to fprintf?

If not, does fprintf need to be checked when it is used this way?

+9
c
source share
5 answers

The C standard says that the stdin , stdout and stderr file streams must be connected somewhere, but they certainly do not indicate where. (C11 §7.21.3. Files No. 7 :

When the program starts, three text streams are predefined and do not need to be opened explicitly - standard input (for reading ordinary input), standard output (for writing regular output) and standard error (for recording diagnostic output). Upon initial opening, the standard error stream is not fully buffered; standard input and standard output streams are fully buffered if and only if it can be determined that the stream does not refer to an interactive device.

It is possible to run a program with redirected standard threads:

 some_program_of_yours >/dev/null 2>&1 </dev/null 

Your entries will be successful, but the information will not go anywhere. A more brutal way to run your program:

 some_program_of_yours >&- 2>&- </dev/null 

This time it was launched without open file streams for stdout and stderr - in violation of the standard. In this example, it is still reading from /dev/null , which means that it is not getting any useful data from stdin .

Many programs do not bother to check that standard I / O channels are open. Many programs did not bother to verify that the error message was successfully written. It’s not always worth the effort to come up with a suitable fallback in the form of Tim Post and whitey04 drafts If you run the ls with suppressed outputs, it will just do what it can and exit with a non-zero status:

 $ ls; echo $? gls 0 $ ls >&- 2>&-; echo $? 2 $ 

(Tested by RHEL Linux.) No need to do more. On the other hand, if your program should run in the background and write to the log file, it probably won’t write much to stderr if it cannot open the log file (or does not find an error in the log). file).

Please note that if you return to syslog(3) (or POSIX ), you have no way of knowing if your calls were “successful” or not; all syslog functions do not return status information. You just have to assume that they were successful. Therefore, this is your last resort.

+13
source share

Typically, you should use some kind of logging system that could (try) handle it for you, or you will need to duplicate this logic in every area of ​​your code that prints standard errors and shuts down.

You have several options:

  • If fprintf does not work, try syslog.
  • If both fail, try creating a crash. {Pid} .log file that contains the information you need in the error report. Check for the presence of these files at startup, as they may inform your program that it crashed earlier.
  • Let network connected users check the configuration parameter, which allows your program to send an error report.

By the way, open() read() and write() are good friends when the fprintf family of functions does not work.

As whitey04 says , sometimes you just have to give up and do your best not to melt with the fireworks. But try to isolate this logic in a small library.

For example:

  best_effort_logger(LOG_CRIT, "Heap corruption likely, bailing out!"); 

It is much cleaner than the if else else if series, where everything can go wrong.

+9
source share

You can put the error on stdout or in another place ... At some point you just need to give an error report, and then refuse.

The key is that your application "gracefully" processes it (for example, the OS does not need to kill it for being bad, and it tells you why it came out [if it can]).

+4
source share

Yes, of course fprintf to stderr may fail. For example, stderr may be an ordinary file, and the disk may run out of free space, or it may be a channel that is closed by the reader, etc.

Should one verify that the operation for failure largely depends on whether the behavior of the program can be improved by checking it. In your case, the only conceivable things you could do if you got an error while printing an error message is to try to print another one (which will almost certainly also fail) or exit the program (which is probably worse than the error message, but maybe not always).

+3
source share

Some programs that really want to log error messages will install an alternative stack at program startup to reserve some memory (see sigaltstack (2) , which can be used by a signal handler (usually SIGSEGV ) to report errors. Depending on the importance logging your error you can explore the use of alternative stacks to preallocate some piece of memory.worth it :), but sometimes you will give something for some hint of t about what happened.

+2
source share

All Articles