1

If an exception is thrown, the lack of a flushed stdout makes it harder to diagnose the issue. Are there any mitigations that can be used? (e.g., termination hooks, compiler flags, etc). I can understand that in a segfault it's probably very difficult to flush, but I would think that it for uncaught exceptions in arbitrary threads, it should be at least theoretically possible.

Note: The situation is complicated slightly by the fact that multiple threads may be used. So catching exceptions in main will not work for other threads.

Barmar
  • 741,623
  • 53
  • 500
  • 612
jhourback
  • 4,381
  • 4
  • 26
  • 31
  • 1
    Why tag this question `c`? – Fiddling Bits Jun 11 '20 at 14:34
  • Just disable buffering. – Barmar Jun 11 '20 at 14:37
  • Why leave your exceptions uncaught? Can't you put a try-catch block around them when launched, and flush in there? For segfaults - you can use sigaction (on Linux/UNIX) to catch segfaults and try flushing things - no guarantees - could even deadlock depending on what was happening when the fault happened. Also consider when stuff is important enough to flush after writing (though doing that too often is slow). If you're really serious, you could write messages into shared memory regions that won't be lost if your app crashes. – Tony Delroy Jun 11 '20 at 14:38
  • @Barmar Why not flush the buffer instead? Disabling buffering has performance implications that may not necessarily be acceptable. – eerorika Jun 11 '20 at 14:40
  • @eerorika Because you can't necessarily do that if the program terminates abnormally. – Barmar Jun 11 '20 at 14:42
  • @Barmar You can if program terminates due to uncaught exception, as in the question. – eerorika Jun 11 '20 at 14:42
  • @eerorika It says "various failure cases". Exception is just an example. – Barmar Jun 11 '20 at 14:43
  • OTOH, it does seem to admit that the solution won't work for segfault. – Barmar Jun 11 '20 at 14:44
  • Write debugging output to `std::cerr`. That's what it's for. It's unit buffered. – Pete Becker Jun 11 '20 at 16:04

1 Answers1

4

When program terminates due to uncaught exception, std::terminate will be called. This calls the terminate handler that has been registered using std::set_terminate. Within this terminate handler, you can flush the standard output streams.

std::terminate is also called in some other cases such as throwing exception out of noexcept function, destruction of joinable std::thread, direct call from user code etc.

This does not help if the program is terminated by the operating system. That can only be solved by disabling buffering. You could try to flush in a signal handler as a desperate measure, but that is not guaranteed to succeed, nor to have desired behaviour, because flushing is not async safe operation.

eerorika
  • 232,697
  • 12
  • 197
  • 326