summarylogtreecommitdiffstats
diff options
context:
space:
mode:
authorhiyuki25782022-04-06 00:50:06 +0900
committerhiyuki25782022-04-06 00:50:06 +0900
commit4278ca3e9a3d01d53d6a9fc6dabd3766360fa83f (patch)
tree99b506e722b04569985a06cb2ea3e0ae2c857109
parent1aa4d79bd009921298f7ae119fe62666e6f7eaa4 (diff)
downloadaur-4278ca3e9a3d01d53d6a9fc6dabd3766360fa83f.tar.gz
Update to trafficserver release 9.1.2
-rw-r--r--.SRCINFO8
-rw-r--r--PKGBUILD16
-rw-r--r--trafficserver.tests_include_catch.hpp.patch730
3 files changed, 745 insertions, 9 deletions
diff --git a/.SRCINFO b/.SRCINFO
index e91231940390..f1687d98f0dd 100644
--- a/.SRCINFO
+++ b/.SRCINFO
@@ -1,6 +1,6 @@
pkgbase = trafficserver
pkgdesc = Apache Traffic Server
- pkgver = 9.0.2
+ pkgver = 9.1.2
pkgrel = 1
url = http://trafficserver.apache.org/
install = trafficserver.install
@@ -61,17 +61,19 @@ pkgbase = trafficserver
backup = etc/trafficserver/plugin.config
backup = etc/trafficserver/logging.yaml
backup = etc/trafficserver/ip_allow.yaml
- source = http://archive.apache.org/dist/trafficserver/trafficserver-9.0.2.tar.bz2
+ source = http://archive.apache.org/dist/trafficserver/trafficserver-9.1.2.tar.bz2
source = trafficserver.tmpfiles
source = trafficserver.sysusers
source = trafficserver.service.in.patch
source = trafficserver.lib_perl_Makefile.in.patch
source = trafficserver.src_tscore_unit_tests.patch
- sha256sums = ff475367aeef27eadefed1290d07241464edb27bccaea86d2a024b6b2b8e0564
+ source = trafficserver.tests_include_catch.hpp.patch
+ sha256sums = 62f27d4e16a515e7ec85393186f909d934a79db41c7905f21d15a9eacb82232f
sha256sums = 8c9dbabfe7a8e0ecf9f3edb3673d1ff0cd63bf79551389047a723479b8d21fac
sha256sums = a4e6a00dea61aa3f98413f092711afb90795ef35676f6a8e3970f4163d360202
sha256sums = fc0b437ef9f9c56ceaaa99eea7075abe15200ff540cfc505e42b0a8f762128b1
sha256sums = 6fb98a044637d6a6d7365b5e49e4a481f556b26d143898ab430e8e8dd7004277
sha256sums = cc56ee24659be4f81f0d70d3e4b0df0954e51647e77599baee4598d4c0339020
+ sha256sums = da2268373955c91be3ee0ef48a2379edc89df1eaebadd3110a6e15b3936aa865
pkgname = trafficserver
diff --git a/PKGBUILD b/PKGBUILD
index 1fed13c95cd9..c1fad546776f 100644
--- a/PKGBUILD
+++ b/PKGBUILD
@@ -1,8 +1,9 @@
-# Maintainer: Galen Sampson <galen.sampson at gmail dot com>
+# Maintainer: hiyuki2578 <tomoka319 at gmail dot com>
+# Contributor: Galen Sampson <galen.sampson at gmail dot com>
# Contributor: David Roheim <david dot roheim at gmail dot com>
pkgname='trafficserver'
-pkgver=9.0.2
+pkgver=9.1.2
pkgrel=1
pkgdesc="Apache Traffic Server"
url="http://trafficserver.apache.org/"
@@ -17,14 +18,16 @@ source=(
trafficserver.sysusers
trafficserver.service.in.patch
trafficserver.lib_perl_Makefile.in.patch
- trafficserver.src_tscore_unit_tests.patch)
+ trafficserver.src_tscore_unit_tests.patch
+ trafficserver.tests_include_catch.hpp.patch)
-sha256sums=('ff475367aeef27eadefed1290d07241464edb27bccaea86d2a024b6b2b8e0564'
+sha256sums=('62f27d4e16a515e7ec85393186f909d934a79db41c7905f21d15a9eacb82232f'
'8c9dbabfe7a8e0ecf9f3edb3673d1ff0cd63bf79551389047a723479b8d21fac'
'a4e6a00dea61aa3f98413f092711afb90795ef35676f6a8e3970f4163d360202'
'fc0b437ef9f9c56ceaaa99eea7075abe15200ff540cfc505e42b0a8f762128b1'
'6fb98a044637d6a6d7365b5e49e4a481f556b26d143898ab430e8e8dd7004277'
- 'cc56ee24659be4f81f0d70d3e4b0df0954e51647e77599baee4598d4c0339020')
+ 'cc56ee24659be4f81f0d70d3e4b0df0954e51647e77599baee4598d4c0339020'
+ 'da2268373955c91be3ee0ef48a2379edc89df1eaebadd3110a6e15b3936aa865')
install=${pkgname}.install
changelog=${pkgname}.changelog
@@ -45,7 +48,7 @@ the UID and GID of the trafficserver user on the build server and then creating
sysusers overrides for the trafficserver user where the package will be
installed. For example (on the server where the package will be deployed):
- # echo 'u trafficserver 999:999 \"Apache Traffic Server\" - > /etc/sysusers.d/trafficserver.conf
+ # echo 'u trafficserver 999:999 \"Apache Traffic Server\" -' > /etc/sysusers.d/trafficserver.conf
This ensures that the post install steps do not clobber administrator defined
or existing cache ownership at the expense of requiring the trafficserver user
@@ -103,6 +106,7 @@ prepare() {
patch -Np0 -u -i ../trafficserver.service.in.patch
patch -Np0 -u -i ../trafficserver.lib_perl_Makefile.in.patch
patch -Np0 -u -i ../trafficserver.src_tscore_unit_tests.patch
+ patch -Np0 -u -i ../trafficserver.tests_include_catch.hpp.patch
}
build() {
diff --git a/trafficserver.tests_include_catch.hpp.patch b/trafficserver.tests_include_catch.hpp.patch
new file mode 100644
index 000000000000..0cb2b0b54104
--- /dev/null
+++ b/trafficserver.tests_include_catch.hpp.patch
@@ -0,0 +1,730 @@
+--- tests/include/catch.hpp.orig 2021-11-09 04:01:21.000000000 +0900
++++ tests/include/catch.hpp 2022-04-06 00:04:07.592474408 +0900
+@@ -1,9 +1,9 @@
+ /*
+- * Catch v2.13.4
+- * Generated: 2020-12-29 14:48:00.116107
++ * Catch v2.13.7
++ * Generated: 2021-07-28 20:29:27.753164
+ * ----------------------------------------------------------
+ * This file has been merged from multiple headers. Please don't edit it directly
+- * Copyright (c) 2020 Two Blue Cubes Ltd. All rights reserved.
++ * Copyright (c) 2021 Two Blue Cubes Ltd. All rights reserved.
+ *
+ * Distributed under the Boost Software License, Version 1.0. (See accompanying
+ * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+@@ -15,7 +15,7 @@
+
+ #define CATCH_VERSION_MAJOR 2
+ #define CATCH_VERSION_MINOR 13
+-#define CATCH_VERSION_PATCH 4
++#define CATCH_VERSION_PATCH 7
+
+ #ifdef __clang__
+ # pragma clang system_header
+@@ -66,13 +66,16 @@
+ #if !defined(CATCH_CONFIG_IMPL_ONLY)
+ // start catch_platform.h
+
++// See e.g.:
++// https://opensource.apple.com/source/CarbonHeaders/CarbonHeaders-18.1/TargetConditionals.h.auto.html
+ #ifdef __APPLE__
+-# include <TargetConditionals.h>
+-# if TARGET_OS_OSX == 1
+-# define CATCH_PLATFORM_MAC
+-# elif TARGET_OS_IPHONE == 1
+-# define CATCH_PLATFORM_IPHONE
+-# endif
++# include <TargetConditionals.h>
++# if (defined(TARGET_OS_OSX) && TARGET_OS_OSX == 1) || \
++ (defined(TARGET_OS_MAC) && TARGET_OS_MAC == 1)
++# define CATCH_PLATFORM_MAC
++# elif (defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE == 1)
++# define CATCH_PLATFORM_IPHONE
++# endif
+
+ #elif defined(linux) || defined(__linux) || defined(__linux__)
+ # define CATCH_PLATFORM_LINUX
+@@ -132,9 +135,9 @@
+
+ #endif
+
+-// We have to avoid both ICC and Clang, because they try to mask themselves
+-// as gcc, and we want only GCC in this block
+-#if defined(__GNUC__) && !defined(__clang__) && !defined(__ICC) && !defined(__CUDACC__)
++// Only GCC compiler should be used in this block, so other compilers trying to
++// mask themselves as GCC should be ignored.
++#if defined(__GNUC__) && !defined(__clang__) && !defined(__ICC) && !defined(__CUDACC__) && !defined(__LCC__)
+ # define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION _Pragma( "GCC diagnostic push" )
+ # define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION _Pragma( "GCC diagnostic pop" )
+
+@@ -323,7 +326,7 @@
+ // Check if byte is available and usable
+ # if __has_include(<cstddef>) && defined(CATCH_CPP17_OR_GREATER)
+ # include <cstddef>
+- # if __cpp_lib_byte > 0
++ # if defined(__cpp_lib_byte) && (__cpp_lib_byte > 0)
+ # define CATCH_INTERNAL_CONFIG_CPP17_BYTE
+ # endif
+ # endif // __has_include(<cstddef>) && defined(CATCH_CPP17_OR_GREATER)
+@@ -5455,6 +5458,8 @@
+ } // namespace Catch
+
+ // end catch_outlier_classification.hpp
++
++#include <iterator>
+ #endif // CATCH_CONFIG_ENABLE_BENCHMARKING
+
+ #include <string>
+@@ -6339,9 +6344,10 @@
+
+ void writeTestCase(TestCaseNode const& testCaseNode);
+
+- void writeSection(std::string const& className,
+- std::string const& rootName,
+- SectionNode const& sectionNode);
++ void writeSection( std::string const& className,
++ std::string const& rootName,
++ SectionNode const& sectionNode,
++ bool testOkToFail );
+
+ void writeAssertions(SectionNode const& sectionNode);
+ void writeAssertion(AssertionStats const& stats);
+@@ -6876,7 +6882,7 @@
+ }
+ iters *= 2;
+ }
+- throw optimized_away_error{};
++ Catch::throw_exception(optimized_away_error{});
+ }
+ } // namespace Detail
+ } // namespace Benchmark
+@@ -6884,6 +6890,7 @@
+
+ // end catch_run_for_at_least.hpp
+ #include <algorithm>
++#include <iterator>
+
+ namespace Catch {
+ namespace Benchmark {
+@@ -7054,8 +7061,8 @@
+ double b2 = bias - z1;
+ double a1 = a(b1);
+ double a2 = a(b2);
+- auto lo = std::max(cumn(a1), 0);
+- auto hi = std::min(cumn(a2), n - 1);
++ auto lo = (std::max)(cumn(a1), 0);
++ auto hi = (std::min)(cumn(a2), n - 1);
+
+ return { point, resample[lo], resample[hi], confidence_level };
+ }
+@@ -7124,7 +7131,9 @@
+ }
+ template <typename Clock>
+ EnvironmentEstimate<FloatDuration<Clock>> estimate_clock_cost(FloatDuration<Clock> resolution) {
+- auto time_limit = std::min(resolution * clock_cost_estimation_tick_limit, FloatDuration<Clock>(clock_cost_estimation_time_limit));
++ auto time_limit = (std::min)(
++ resolution * clock_cost_estimation_tick_limit,
++ FloatDuration<Clock>(clock_cost_estimation_time_limit));
+ auto time_clock = [](int k) {
+ return Detail::measure<Clock>([k] {
+ for (int i = 0; i < k; ++i) {
+@@ -7771,7 +7780,7 @@
+ double sb = stddev.point;
+ double mn = mean.point / n;
+ double mg_min = mn / 2.;
+- double sg = std::min(mg_min / 4., sb / std::sqrt(n));
++ double sg = (std::min)(mg_min / 4., sb / std::sqrt(n));
+ double sg2 = sg * sg;
+ double sb2 = sb * sb;
+
+@@ -7790,7 +7799,7 @@
+ return (nc / n) * (sb2 - nc * sg2);
+ };
+
+- return std::min(var_out(1), var_out(std::min(c_max(0.), c_max(mg_min)))) / sb2;
++ return (std::min)(var_out(1), var_out((std::min)(c_max(0.), c_max(mg_min)))) / sb2;
+ }
+
+ bootstrap_analysis analyse_samples(double confidence_level, int n_resamples, std::vector<double>::iterator first, std::vector<double>::iterator last) {
+@@ -7980,86 +7989,58 @@
+
+ // start catch_fatal_condition.h
+
+-// start catch_windows_h_proxy.h
+-
+-
+-#if defined(CATCH_PLATFORM_WINDOWS)
+-
+-#if !defined(NOMINMAX) && !defined(CATCH_CONFIG_NO_NOMINMAX)
+-# define CATCH_DEFINED_NOMINMAX
+-# define NOMINMAX
+-#endif
+-#if !defined(WIN32_LEAN_AND_MEAN) && !defined(CATCH_CONFIG_NO_WIN32_LEAN_AND_MEAN)
+-# define CATCH_DEFINED_WIN32_LEAN_AND_MEAN
+-# define WIN32_LEAN_AND_MEAN
+-#endif
+-
+-#ifdef __AFXDLL
+-#include <AfxWin.h>
+-#else
+-#include <windows.h>
+-#endif
+-
+-#ifdef CATCH_DEFINED_NOMINMAX
+-# undef NOMINMAX
+-#endif
+-#ifdef CATCH_DEFINED_WIN32_LEAN_AND_MEAN
+-# undef WIN32_LEAN_AND_MEAN
+-#endif
+-
+-#endif // defined(CATCH_PLATFORM_WINDOWS)
+-
+-// end catch_windows_h_proxy.h
+-#if defined( CATCH_CONFIG_WINDOWS_SEH )
++#include <cassert>
+
+ namespace Catch {
+
+- struct FatalConditionHandler {
+-
+- static LONG CALLBACK handleVectoredException(PEXCEPTION_POINTERS ExceptionInfo);
++ // 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();
+- static void reset();
+ ~FatalConditionHandler();
+
+- private:
+- static bool isSet;
+- static ULONG guaranteeSize;
+- static PVOID exceptionHandlerHandle;
+- };
+-
+-} // namespace Catch
+-
+-#elif defined ( CATCH_CONFIG_POSIX_SIGNALS )
+-
+-#include <signal.h>
+-
+-namespace Catch {
+-
+- struct FatalConditionHandler {
+-
+- static bool isSet;
+- static struct sigaction oldSigActions[];
+- static stack_t oldSigStack;
+- static char altStackMem[];
+-
+- static void handleSignal( int sig );
++ void engage() {
++ assert(!m_started && "Handler cannot be installed twice.");
++ m_started = true;
++ engage_platform();
++ }
+
+- FatalConditionHandler();
+- ~FatalConditionHandler();
+- static void reset();
++ void disengage() {
++ assert(m_started && "Handler cannot be uninstalled without being installed first");
++ m_started = false;
++ disengage_platform();
++ }
+ };
+
+-} // namespace Catch
+-
+-#else
+-
+-namespace Catch {
+- struct FatalConditionHandler {
+- void reset();
++ //! 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();
++ }
+ };
+-}
+
+-#endif
++} // end namespace Catch
+
+ // end catch_fatal_condition.h
+ #include <string>
+@@ -8185,6 +8166,7 @@
+ std::vector<SectionEndInfo> m_unfinishedSections;
+ std::vector<ITracker*> m_activeSections;
+ TrackerContext m_trackerContext;
++ FatalConditionHandler m_fatalConditionhandler;
+ bool m_lastAssertionPassed = false;
+ bool m_shouldReportUnexpected = true;
+ bool m_includeSuccessfulResults;
+@@ -10057,6 +10039,36 @@
+ }
+
+ // end catch_errno_guard.h
++// start catch_windows_h_proxy.h
++
++
++#if defined(CATCH_PLATFORM_WINDOWS)
++
++#if !defined(NOMINMAX) && !defined(CATCH_CONFIG_NO_NOMINMAX)
++# define CATCH_DEFINED_NOMINMAX
++# define NOMINMAX
++#endif
++#if !defined(WIN32_LEAN_AND_MEAN) && !defined(CATCH_CONFIG_NO_WIN32_LEAN_AND_MEAN)
++# define CATCH_DEFINED_WIN32_LEAN_AND_MEAN
++# define WIN32_LEAN_AND_MEAN
++#endif
++
++#ifdef __AFXDLL
++#include <AfxWin.h>
++#else
++#include <windows.h>
++#endif
++
++#ifdef CATCH_DEFINED_NOMINMAX
++# undef NOMINMAX
++#endif
++#ifdef CATCH_DEFINED_WIN32_LEAN_AND_MEAN
++# undef WIN32_LEAN_AND_MEAN
++#endif
++
++#endif // defined(CATCH_PLATFORM_WINDOWS)
++
++// end catch_windows_h_proxy.h
+ #include <sstream>
+
+ namespace Catch {
+@@ -10573,7 +10585,7 @@
+ // Extracts the actual name part of an enum instance
+ // In other words, it returns the Blue part of Bikeshed::Colour::Blue
+ StringRef extractInstanceName(StringRef enumInstance) {
+- // Find last occurence of ":"
++ // Find last occurrence of ":"
+ size_t name_start = enumInstance.size();
+ while (name_start > 0 && enumInstance[name_start - 1] != ':') {
+ --name_start;
+@@ -10735,25 +10747,47 @@
+ // end catch_exception_translator_registry.cpp
+ // start catch_fatal_condition.cpp
+
+-#if defined(__GNUC__)
+-# pragma GCC diagnostic push
+-# pragma GCC diagnostic ignored "-Wmissing-field-initializers"
+-#endif
++#include <algorithm>
++
++#if !defined( CATCH_CONFIG_WINDOWS_SEH ) && !defined( CATCH_CONFIG_POSIX_SIGNALS )
++
++namespace Catch {
++
++ // If neither SEH nor signal handling is required, the handler impls
++ // do not have to do anything, and can be empty.
++ void FatalConditionHandler::engage_platform() {}
++ void FatalConditionHandler::disengage_platform() {}
++ FatalConditionHandler::FatalConditionHandler() = default;
++ FatalConditionHandler::~FatalConditionHandler() = default;
++
++} // end namespace Catch
++
++#endif // !CATCH_CONFIG_WINDOWS_SEH && !CATCH_CONFIG_POSIX_SIGNALS
++
++#if defined( CATCH_CONFIG_WINDOWS_SEH ) && defined( CATCH_CONFIG_POSIX_SIGNALS )
++#error "Inconsistent configuration: Windows' SEH handling and POSIX signals cannot be enabled at the same time"
++#endif // CATCH_CONFIG_WINDOWS_SEH && CATCH_CONFIG_POSIX_SIGNALS
+
+ #if defined( CATCH_CONFIG_WINDOWS_SEH ) || defined( CATCH_CONFIG_POSIX_SIGNALS )
+
+ namespace {
+- // Report the error condition
++ //! Signals fatal error message to the run context
+ void reportFatal( char const * const message ) {
+ Catch::getCurrentContext().getResultCapture()->handleFatalErrorCondition( message );
+ }
+-}
+
+-#endif // signals/SEH handling
++ //! Minimal size Catch2 needs for its own fatal error handling.
++ //! Picked anecdotally, so it might not be sufficient on all
++ //! platforms, and for all configurations.
++ constexpr std::size_t minStackSizeForErrors = 32 * 1024;
++} // end unnamed namespace
++
++#endif // CATCH_CONFIG_WINDOWS_SEH || CATCH_CONFIG_POSIX_SIGNALS
+
+ #if defined( CATCH_CONFIG_WINDOWS_SEH )
+
+ namespace Catch {
++
+ struct SignalDefs { DWORD id; const char* name; };
+
+ // There is no 1-1 mapping between signals and windows exceptions.
+@@ -10766,7 +10800,7 @@
+ { static_cast<DWORD>(EXCEPTION_INT_DIVIDE_BY_ZERO), "Divide by zero error" },
+ };
+
+- LONG CALLBACK FatalConditionHandler::handleVectoredException(PEXCEPTION_POINTERS ExceptionInfo) {
++ static LONG CALLBACK handleVectoredException(PEXCEPTION_POINTERS ExceptionInfo) {
+ for (auto const& def : signalDefs) {
+ if (ExceptionInfo->ExceptionRecord->ExceptionCode == def.id) {
+ reportFatal(def.name);
+@@ -10777,38 +10811,50 @@
+ return EXCEPTION_CONTINUE_SEARCH;
+ }
+
++ // Since we do not support multiple instantiations, we put these
++ // into global variables and rely on cleaning them up in outlined
++ // constructors/destructors
++ static PVOID exceptionHandlerHandle = nullptr;
++
++ // For MSVC, we reserve part of the stack memory for handling
++ // memory overflow structured exception.
+ FatalConditionHandler::FatalConditionHandler() {
+- isSet = true;
+- // 32k seems enough for Catch to handle stack overflow,
+- // but the value was found experimentally, so there is no strong guarantee
+- guaranteeSize = 32 * 1024;
+- exceptionHandlerHandle = nullptr;
++ ULONG guaranteeSize = static_cast<ULONG>(minStackSizeForErrors);
++ if (!SetThreadStackGuarantee(&guaranteeSize)) {
++ // We do not want to fully error out, because needing
++ // the stack reserve should be rare enough anyway.
++ Catch::cerr()
++ << "Failed to reserve piece of stack."
++ << " Stack overflows will not be reported successfully.";
++ }
++ }
++
++ // We do not attempt to unset the stack guarantee, because
++ // Windows does not support lowering the stack size guarantee.
++ FatalConditionHandler::~FatalConditionHandler() = default;
++
++ void FatalConditionHandler::engage_platform() {
+ // Register as first handler in current chain
+ exceptionHandlerHandle = AddVectoredExceptionHandler(1, handleVectoredException);
+- // Pass in guarantee size to be filled
+- SetThreadStackGuarantee(&guaranteeSize);
++ if (!exceptionHandlerHandle) {
++ CATCH_RUNTIME_ERROR("Could not register vectored exception handler");
++ }
+ }
+
+- void FatalConditionHandler::reset() {
+- if (isSet) {
+- RemoveVectoredExceptionHandler(exceptionHandlerHandle);
+- SetThreadStackGuarantee(&guaranteeSize);
+- exceptionHandlerHandle = nullptr;
+- isSet = false;
++ void FatalConditionHandler::disengage_platform() {
++ if (!RemoveVectoredExceptionHandler(exceptionHandlerHandle)) {
++ CATCH_RUNTIME_ERROR("Could not unregister vectored exception handler");
+ }
++ exceptionHandlerHandle = nullptr;
+ }
+
+- FatalConditionHandler::~FatalConditionHandler() {
+- reset();
+- }
++} // end namespace Catch
+
+-bool FatalConditionHandler::isSet = false;
+-ULONG FatalConditionHandler::guaranteeSize = 0;
+-PVOID FatalConditionHandler::exceptionHandlerHandle = nullptr;
++#endif // CATCH_CONFIG_WINDOWS_SEH
+
+-} // namespace Catch
++#if defined( CATCH_CONFIG_POSIX_SIGNALS )
+
+-#elif defined( CATCH_CONFIG_POSIX_SIGNALS )
++#include <signal.h>
+
+ namespace Catch {
+
+@@ -10817,10 +10863,6 @@
+ const char* name;
+ };
+
+- // 32kb for the alternate stack seems to be sufficient. However, this value
+- // is experimentally determined, so that's not guaranteed.
+- static constexpr std::size_t sigStackSize = 32768 >= MINSIGSTKSZ ? 32768 : MINSIGSTKSZ;
+-
+ static SignalDefs signalDefs[] = {
+ { SIGINT, "SIGINT - Terminal interrupt signal" },
+ { SIGILL, "SIGILL - Illegal instruction signal" },
+@@ -10830,7 +10872,32 @@
+ { SIGABRT, "SIGABRT - Abort (abnormal termination) signal" }
+ };
+
+- void FatalConditionHandler::handleSignal( int sig ) {
++// Older GCCs trigger -Wmissing-field-initializers for T foo = {}
++// which is zero initialization, but not explicit. We want to avoid
++// that.
++#if defined(__GNUC__)
++# pragma GCC diagnostic push
++# pragma GCC diagnostic ignored "-Wmissing-field-initializers"
++#endif
++
++ static char* altStackMem = nullptr;
++ static std::size_t altStackSize = 0;
++ static stack_t oldSigStack{};
++ static struct sigaction oldSigActions[sizeof(signalDefs) / sizeof(SignalDefs)]{};
++
++ static void restorePreviousSignalHandlers() {
++ // We set signal handlers back to the previous ones. Hopefully
++ // nobody overwrote them in the meantime, and doesn't expect
++ // their signal handlers to live past ours given that they
++ // installed them after ours..
++ for (std::size_t i = 0; i < sizeof(signalDefs) / sizeof(SignalDefs); ++i) {
++ sigaction(signalDefs[i].id, &oldSigActions[i], nullptr);
++ }
++ // Return the old stack
++ sigaltstack(&oldSigStack, nullptr);
++ }
++
++ static void handleSignal( int sig ) {
+ char const * name = "<unknown signal>";
+ for (auto const& def : signalDefs) {
+ if (sig == def.id) {
+@@ -10838,16 +10905,33 @@
+ break;
+ }
+ }
+- reset();
+- reportFatal(name);
++ // We need to restore previous signal handlers and let them do
++ // their thing, so that the users can have the debugger break
++ // when a signal is raised, and so on.
++ restorePreviousSignalHandlers();
++ reportFatal( name );
+ raise( sig );
+ }
+
+ FatalConditionHandler::FatalConditionHandler() {
+- isSet = true;
++ assert(!altStackMem && "Cannot initialize POSIX signal handler when one already exists");
++ if (altStackSize == 0) {
++ altStackSize = std::max(static_cast<size_t>(SIGSTKSZ), minStackSizeForErrors);
++ }
++ altStackMem = new char[altStackSize]();
++ }
++
++ FatalConditionHandler::~FatalConditionHandler() {
++ delete[] altStackMem;
++ // We signal that another instance can be constructed by zeroing
++ // out the pointer.
++ altStackMem = nullptr;
++ }
++
++ void FatalConditionHandler::engage_platform() {
+ stack_t sigStack;
+ sigStack.ss_sp = altStackMem;
+- sigStack.ss_size = sigStackSize;
++ sigStack.ss_size = altStackSize;
+ sigStack.ss_flags = 0;
+ sigaltstack(&sigStack, &oldSigStack);
+ struct sigaction sa = { };
+@@ -10859,40 +10943,17 @@
+ }
+ }
+
+- FatalConditionHandler::~FatalConditionHandler() {
+- reset();
+- }
++#if defined(__GNUC__)
++# pragma GCC diagnostic pop
++#endif
+
+- void FatalConditionHandler::reset() {
+- if( isSet ) {
+- // Set signals back to previous values -- hopefully nobody overwrote them in the meantime
+- for( std::size_t i = 0; i < sizeof(signalDefs)/sizeof(SignalDefs); ++i ) {
+- sigaction(signalDefs[i].id, &oldSigActions[i], nullptr);
+- }
+- // Return the old stack
+- sigaltstack(&oldSigStack, nullptr);
+- isSet = false;
+- }
++ void FatalConditionHandler::disengage_platform() {
++ restorePreviousSignalHandlers();
+ }
+
+- bool FatalConditionHandler::isSet = false;
+- struct sigaction FatalConditionHandler::oldSigActions[sizeof(signalDefs)/sizeof(SignalDefs)] = {};
+- stack_t FatalConditionHandler::oldSigStack = {};
+- char FatalConditionHandler::altStackMem[sigStackSize] = {};
+-
+-} // namespace Catch
+-
+-#else
+-
+-namespace Catch {
+- void FatalConditionHandler::reset() {}
+-}
+-
+-#endif // signals/SEH handling
++} // end namespace Catch
+
+-#if defined(__GNUC__)
+-# pragma GCC diagnostic pop
+-#endif
++#endif // CATCH_CONFIG_POSIX_SIGNALS
+ // end catch_fatal_condition.cpp
+ // start catch_generators.cpp
+
+@@ -11447,7 +11508,8 @@
+ return lhs == rhs;
+ }
+
+- auto ulpDiff = std::abs(lc - rc);
++ // static cast as a workaround for IBM XLC
++ auto ulpDiff = std::abs(static_cast<FP>(lc - rc));
+ return static_cast<uint64_t>(ulpDiff) <= maxUlpDiff;
+ }
+
+@@ -11621,7 +11683,6 @@
+
+ } // namespace Matchers
+ } // namespace Catch
+-
+ // end catch_matchers_floating.cpp
+ // start catch_matchers_generic.cpp
+
+@@ -12955,9 +13016,8 @@
+ }
+
+ void RunContext::invokeActiveTestCase() {
+- FatalConditionHandler fatalConditionHandler; // Handle signals
++ FatalConditionHandlerGuard _(&m_fatalConditionhandler);
+ m_activeTestCase->invoke();
+- fatalConditionHandler.reset();
+ }
+
+ void RunContext::handleUnfinishedSections() {
+@@ -15320,7 +15380,7 @@
+ }
+
+ Version const& libraryVersion() {
+- static Version version( 2, 13, 4, "", 0 );
++ static Version version( 2, 13, 7, "", 0 );
+ return version;
+ }
+
+@@ -16733,6 +16793,7 @@
+ #include <sstream>
+ #include <ctime>
+ #include <algorithm>
++#include <iomanip>
+
+ namespace Catch {
+
+@@ -16760,7 +16821,7 @@
+ #else
+ std::strftime(timeStamp, timeStampSize, fmt, timeInfo);
+ #endif
+- return std::string(timeStamp);
++ return std::string(timeStamp, timeStampSize-1);
+ }
+
+ std::string fileNameTag(const std::vector<std::string> &tags) {
+@@ -16771,6 +16832,17 @@
+ return it->substr(1);
+ return std::string();
+ }
++
++ // Formats the duration in seconds to 3 decimal places.
++ // This is done because some genius defined Maven Surefire schema
++ // in a way that only accepts 3 decimal places, and tools like
++ // Jenkins use that schema for validation JUnit reporter output.
++ std::string formatDuration( double seconds ) {
++ ReusableStringStream rss;
++ rss << std::fixed << std::setprecision( 3 ) << seconds;
++ return rss.str();
++ }
++
+ } // anonymous namespace
+
+ JunitReporter::JunitReporter( ReporterConfig const& _config )
+@@ -16840,7 +16912,7 @@
+ if( m_config->showDurations() == ShowDurations::Never )
+ xml.writeAttribute( "time", "" );
+ else
+- xml.writeAttribute( "time", suiteTime );
++ xml.writeAttribute( "time", formatDuration( suiteTime ) );
+ xml.writeAttribute( "timestamp", getCurrentTimestamp() );
+
+ // Write properties if there are any
+@@ -16885,12 +16957,13 @@
+ if ( !m_config->name().empty() )
+ className = m_config->name() + "." + className;
+
+- writeSection( className, "", rootSection );
++ writeSection( className, "", rootSection, stats.testInfo.okToFail() );
+ }
+
+- void JunitReporter::writeSection( std::string const& className,
+- std::string const& rootName,
+- SectionNode const& sectionNode ) {
++ void JunitReporter::writeSection( std::string const& className,
++ std::string const& rootName,
++ SectionNode const& sectionNode,
++ bool testOkToFail) {
+ std::string name = trim( sectionNode.stats.sectionInfo.name );
+ if( !rootName.empty() )
+ name = rootName + '/' + name;
+@@ -16907,13 +16980,18 @@
+ xml.writeAttribute( "classname", className );
+ xml.writeAttribute( "name", name );
+ }
+- xml.writeAttribute( "time", ::Catch::Detail::stringify( sectionNode.stats.durationInSeconds ) );
++ xml.writeAttribute( "time", formatDuration( sectionNode.stats.durationInSeconds ) );
+ // This is not ideal, but it should be enough to mimic gtest's
+ // junit output.
+ // Ideally the JUnit reporter would also handle `skipTest`
+ // events and write those out appropriately.
+ xml.writeAttribute( "status", "run" );
+
++ if (sectionNode.stats.assertions.failedButOk) {
++ xml.scopedElement("skipped")
++ .writeAttribute("message", "TEST_CASE tagged with !mayfail");
++ }
++
+ writeAssertions( sectionNode );
+
+ if( !sectionNode.stdOut.empty() )
+@@ -16923,9 +17001,9 @@
+ }
+ for( auto const& childNode : sectionNode.childSections )
+ if( className.empty() )
+- writeSection( name, "", *childNode );
++ writeSection( name, "", *childNode, testOkToFail );
+ else
+- writeSection( className, name, *childNode );
++ writeSection( className, name, *childNode, testOkToFail );
+ }
+
+ void JunitReporter::writeAssertions( SectionNode const& sectionNode ) {