libstdc++: Handle exceptions in std::ostream::sentry destructor
Because basic_ostream::sentry::~sentry is implicitly noexcept, we can't let any exceptions escape from it, or the program would terminate. If the streambuf's sync() function throws, or if it returns an error and setting badbit in the stream state throws, then the program would terminate. LWG 835 intended to prevent exceptions from being thrown by the std::basic_ostream::sentry destructor, but failed to cover the case where the streambuf's sync() member throws an exception. LWG 4188 is needed to fix that part. In any case, LWG 835 was never implemented for libstdc++ so this does that, as well as my proposed fix for 4188 (that badbit should be set if pubsync() exits via an exception). In order to avoid a second try-catch block to handle an exception that might be thrown by setting badbit, this introduces an RAII helper class that temporarily clears the stream's exceptions mask, then restores it afterwards. The try-catch block doesn't handle the forced_unwind exception explicitly, because catching and rethrowing that would just terminate when it reached the sentry's implicit noexcept(true) anyway. libstdc++-v3/ChangeLog: * include/bits/ostream.h (basic_ostream::_Disable_exceptions): RAII helper type. (basic_ostream::sentry::~sentry): Use _Disable_exceptions. Add try-catch block around call to pubsync. * testsuite/27_io/basic_ostream/exceptions/char/lwg4188.cc: New test. * testsuite/27_io/basic_ostream/exceptions/wchar_t/lwg4188.cc: New test.
Showing
- libstdc++-v3/include/bits/ostream.h 40 additions, 8 deletionslibstdc++-v3/include/bits/ostream.h
- libstdc++-v3/testsuite/27_io/basic_ostream/exceptions/char/lwg4188.cc 50 additions, 0 deletions.../testsuite/27_io/basic_ostream/exceptions/char/lwg4188.cc
- libstdc++-v3/testsuite/27_io/basic_ostream/exceptions/wchar_t/lwg4188.cc 50 additions, 0 deletions...stsuite/27_io/basic_ostream/exceptions/wchar_t/lwg4188.cc
Loading
Please register or sign in to comment