HikoGUI
A low latency retained GUI
Loading...
Searching...
No Matches
terminate.hpp
Go to the documentation of this file.
1// Copyright Take Vos 2023.
2// Distributed under the Boost Software License, Version 1.0.
3// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
4
8#pragma once
9
10#include "../macros.hpp"
11#include "dialog.hpp"
12#include "debugger.hpp"
13#include <exception>
14#include <stdexcept>
15#include <atomic>
16#include <bit>
17#include <format>
18#include <iostream>
19#include <functional>
20#include <mutex>
21#include <print>
22#include <cstdio>
23#include <stacktrace>
24
25hi_export_module(hikogui.utility.terminate);
26
27hi_export namespace hi {
28inline namespace v1 {
29namespace detail {
30
31inline std::mutex terminate_mutex;
32
33inline std::vector<std::function<void()>> atterminate_functions;
34
35inline void call_atterminate() noexcept
36{
37 auto const lock = std::scoped_lock(terminate_mutex);
38 for (auto it = atterminate_functions.rbegin(); it != atterminate_functions.rend(); ++it) {
39 (*it)();
40 }
41}
42
43} // namespace detail
44
48inline void atterminate(std::function<void()> f) noexcept
49{
50 auto const lock = std::scoped_lock(detail::terminate_mutex);
51 detail::atterminate_functions.push_back(std::move(f));
52}
53
59
66inline void terminate_handler() noexcept
67{
68 using namespace std::literals;
69
70 detail::call_atterminate();
71
72 auto title = std::string{};
73 auto message = std::string{};
74
75 auto const ep = std::current_exception();
76 if (ep) {
77 try {
79
80 } catch (std::exception const& e) {
81 title = "Unhandled std::exception."s;
82 message += e.what();
83
84 } catch (...) {
85 title = "Unhandled unknown exception."s;
86 message += "<no data>"s;
87 }
88
89 } else {
90 title = "Abnormal termination."s;
91 if (auto message_cstr = get_debug_message()) {
92 message += message_cstr;
93 } else {
94 message += "<unknown>";
95 }
96 }
97
98 // Append a stacktrace.
99 message += "\n\nStack Trace:\n";
100
101 auto stack_trace = std::stacktrace::current(0, 25);
102
103 auto depth = 0;
104 for (auto entry : stack_trace) {
105 if (entry and not(entry.source_file().empty() and entry.source_line() == 0 and entry.description().empty())) {
106 message += std::format("{}. {}:{} {}\n", depth, entry.source_file(), entry.source_line(), entry.description());
107 } else {
108 message += std::format("{}. <information is unavailable>\n", depth);
109 }
110 ++depth;
111 }
112
113 if (not dialog(title, message)) {
114 // Failed to show the dialog box.
115 std::println(stderr, "{}\n{}", title, message);
116 }
117
118 // Chain the optional older terminate handler.
121 }
122}
123
124} // namespace v1
125} // namespace hi::v1
The HikoGUI namespace.
Definition array_generic.hpp:20
std::terminate_handler old_terminate_handler
The old terminate handler.
Definition terminate.hpp:58
void atterminate(std::function< void()> f) noexcept
Register functions that need to be called on std::terminate().
Definition terminate.hpp:48
std::expected< dialog_button, std::error_code > dialog(std::string_view title, std::string_view text, dialog_button_mask button_mask=dialog_button_mask::ok) noexcept
Display a modal dialog.
Definition dialog_win32_impl.hpp:20
void terminate_handler() noexcept
The HikoGUI terminate handler.
Definition terminate.hpp:66
DOXYGEN BUG.
Definition algorithm_misc.hpp:20
T current_exception(T... args)
T lock(T... args)
T move(T... args)
T rethrow_exception(T... args)
T what(T... args)