mirror of
https://github.com/catchorg/Catch2.git
synced 2025-04-28 19:53:52 +00:00
Because new glibc has changed `MINSIGSTKSZ` to be a syscall instead of being constant, the signal posix handling needed changes, as it used the value in constexpr context, for deciding size of an array. It would be simple to fix it by having the handler determine the signal handling stack size and allocate the memory every time the handler is being installed, but that would add another allocation and a syscall every time a test case is entered. Instead, I split apart the idea of preparing fatal error handlers, and engaging them, so that the memory can be allocated only once and still be guarded by RAII. Also turns out that Catch2's use of `MINSIGSTKSZ` was wrong, and we should've been using `SIGSTKSZ` the whole time, which we use now. Closes #2178
70 lines
2.2 KiB
C++
70 lines
2.2 KiB
C++
|
|
// Copyright Catch2 Authors
|
|
// Distributed under the Boost Software License, Version 1.0.
|
|
// (See accompanying file LICENSE_1_0.txt or copy at
|
|
// https://www.boost.org/LICENSE_1_0.txt)
|
|
|
|
// SPDX-License-Identifier: BSL-1.0
|
|
#ifndef CATCH_FATAL_CONDITION_HANDLER_HPP_INCLUDED
|
|
#define CATCH_FATAL_CONDITION_HANDLER_HPP_INCLUDED
|
|
|
|
#include <catch2/internal/catch_platform.hpp>
|
|
#include <catch2/internal/catch_compiler_capabilities.hpp>
|
|
|
|
#include <cassert>
|
|
|
|
namespace Catch {
|
|
|
|
/**
|
|
* Wrapper for platform-specific fatal error (signals/SEH) handlers
|
|
*
|
|
* Tries to be cooperative with other handlers, and not step over
|
|
* other handlers. This means that unknown structured exceptions
|
|
* are passed on, previous signal handlers are called, and so on.
|
|
*
|
|
* Can only be instantiated once, and assumes that once a signal
|
|
* is caught, the binary will end up terminating. Thus, there
|
|
*/
|
|
class FatalConditionHandler {
|
|
bool m_started = false;
|
|
|
|
// Install/disengage implementation for specific platform.
|
|
// Should be if-defed to work on current platform, can assume
|
|
// engage-disengage 1:1 pairing.
|
|
void engage_platform();
|
|
void disengage_platform();
|
|
public:
|
|
// Should also have platform-specific implementations as needed
|
|
FatalConditionHandler();
|
|
~FatalConditionHandler();
|
|
|
|
void engage() {
|
|
assert(!m_started && "Handler cannot be installed twice.");
|
|
m_started = true;
|
|
engage_platform();
|
|
}
|
|
|
|
void disengage() {
|
|
assert(m_started && "Handler cannot be uninstalled without being installed first");
|
|
m_started = false;
|
|
disengage_platform();
|
|
}
|
|
};
|
|
|
|
//! Simple RAII guard for (dis)engaging the FatalConditionHandler
|
|
class FatalConditionHandlerGuard {
|
|
FatalConditionHandler* m_handler;
|
|
public:
|
|
FatalConditionHandlerGuard(FatalConditionHandler* handler):
|
|
m_handler(handler) {
|
|
m_handler->engage();
|
|
}
|
|
~FatalConditionHandlerGuard() {
|
|
m_handler->disengage();
|
|
}
|
|
};
|
|
|
|
} // end namespace Catch
|
|
|
|
#endif // CATCH_FATAL_CONDITION_HANDLER_HPP_INCLUDED
|