diff --git a/include/boost/core/verbose_terminate_handler.hpp b/include/boost/core/verbose_terminate_handler.hpp new file mode 100644 index 0000000..b831b49 --- /dev/null +++ b/include/boost/core/verbose_terminate_handler.hpp @@ -0,0 +1,87 @@ +#ifndef BOOST_CORE_VERBOSE_TERMINATE_HANDLER_HPP_INCLUDED +#define BOOST_CORE_VERBOSE_TERMINATE_HANDLER_HPP_INCLUDED + +// MS compatible compilers support #pragma once + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +// Copyright 2022 Peter Dimov +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +#include +#include +#include +#include +#include +#include +#include + +namespace boost +{ +namespace core +{ + +BOOST_NORETURN void verbose_terminate_handler() +{ + std::set_terminate( 0 ); + +#if defined(BOOST_NO_EXCEPTIONS) + + std::fputs( "std::terminate called with exceptions disabled", stderr ); + +#else + + try + { + throw; + } + catch( std::exception const& x ) + { +#if defined(BOOST_NO_RTTI) + + char const * typeid_name = "unknown (RTTI is disabled)"; + +#else + + char const * typeid_name = typeid( x ).name(); + + boost::core::scoped_demangled_name typeid_demangled_name( typeid_name ); + + if( typeid_demangled_name.get() != 0 ) + { + typeid_name = typeid_demangled_name.get(); + } + +#endif + + boost::source_location loc = boost::get_throw_location( x ); + + std::fprintf( stderr, + "std::terminate called after throwing an exception:\n" + " type: %s\n" + " what(): %s\n" + " location: %s:%lu:%lu in function '%s'\n", + + typeid_name, + x.what(), + loc.file_name(), static_cast( loc.line() ), + static_cast( loc.column() ), loc.function_name() + ); + } + catch( ... ) + { + std::fputs( "std::terminate called after throwing an unknown exception", stderr ); + } + +#endif + + std::abort(); +} + +} // namespace core +} // namespace boost + +#endif // #ifndef BOOST_CORE_VERBOSE_TERMINATE_HANDLER_HPP_INCLUDED diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index fbf6b16..28a5be2 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -331,5 +331,10 @@ run as_writable_bytes_test.cpp ; run splitmix64_test.cpp : : : $(pedantic-errors) ; +run-fail verbose_terminate_handler_fail.cpp ; +run-fail verbose_terminate_handler_fail.cpp : : : off : verbose_terminate_handler_fail_nx ; +run-fail verbose_terminate_handler_fail.cpp : : : off : verbose_terminate_handler_fail_nr ; +run-fail verbose_terminate_handler_fail.cpp : : : off off : verbose_terminate_handler_fail_nxr ; + use-project /boost/core/swap : ./swap ; build-project ./swap ; diff --git a/test/verbose_terminate_handler_fail.cpp b/test/verbose_terminate_handler_fail.cpp new file mode 100644 index 0000000..07f8ef5 --- /dev/null +++ b/test/verbose_terminate_handler_fail.cpp @@ -0,0 +1,48 @@ +// Copyright 2022 Peter Dimov +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +#if defined(_MSC_VER) +# pragma warning(disable: 4702) // unreachable code +#endif + +#include +#include +#include +#include +#if defined(_MSC_VER) && defined(_CPPLIB_VER) && defined(_DEBUG) +# include +#endif + +int main() +{ +#if defined(_MSC_VER) && (_MSC_VER > 1310) + // disable message boxes on assert(), abort() + ::_set_abort_behavior(0, _WRITE_ABORT_MSG | _CALL_REPORTFAULT); +#endif +#if defined(_MSC_VER) && defined(_CPPLIB_VER) && defined(_DEBUG) + // disable message boxes on iterator debugging violations + _CrtSetReportMode( _CRT_ASSERT, _CRTDBG_MODE_FILE ); + _CrtSetReportFile( _CRT_ASSERT, _CRTDBG_FILE_STDERR ); +#endif + + std::set_terminate( boost::core::verbose_terminate_handler ); + + boost::throw_with_location( std::exception() ); +} + +#if defined(BOOST_NO_EXCEPTIONS) + +void boost::throw_exception( std::exception const& x ) +{ + std::fprintf( stderr, "throw_exception: %s\n\n", x.what() ); + std::terminate(); +} + +void boost::throw_exception( std::exception const& x, boost::source_location const& ) +{ + std::fprintf( stderr, "throw_exception: %s\n\n", x.what() ); + std::terminate(); +} + +#endif