Skip to content

Commit 808dfbc

Browse files
committed
Fix failure to build on Mac OS with ARM CPUs.
1 parent 743faa0 commit 808dfbc

File tree

2 files changed

+81
-36
lines changed

2 files changed

+81
-36
lines changed

include/quickcpplib/revision.hpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
// Note the second line of this file must ALWAYS be the git SHA, third line ALWAYS the git SHA update time
2-
#define QUICKCPPLIB_PREVIOUS_COMMIT_REF 2af3839551eacd2152892d7197b27cd5b87deb38
3-
#define QUICKCPPLIB_PREVIOUS_COMMIT_DATE "2023-12-08 21:07:16 +00:00"
4-
#define QUICKCPPLIB_PREVIOUS_COMMIT_UNIQUE 2af38395
2+
#define QUICKCPPLIB_PREVIOUS_COMMIT_REF 72277c70f925829935a2af846731ab36063ec16f
3+
#define QUICKCPPLIB_PREVIOUS_COMMIT_DATE "2023-12-08 21:13:22 +00:00"
4+
#define QUICKCPPLIB_PREVIOUS_COMMIT_UNIQUE 72277c70

test/signal_guard.cpp

Lines changed: 78 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -79,14 +79,16 @@ BOOST_AUTO_TEST_CASE(signal_guard / works / threadlocal, "Tests that signal_guar
7979
std::cout << "2" << std::endl;
8080
{
8181
int ret = signal_guard(
82-
signalc_set::cxx_termination, []() -> int { std::terminate(); }, [](const raised_signal_info * /*unused*/) -> int { return 78; });
82+
signalc_set::cxx_termination, []() -> int { std::terminate(); },
83+
[](const raised_signal_info * /*unused*/) -> int { return 78; });
8384
BOOST_CHECK(ret == 78);
8485
}
8586
std::cout << "3" << std::endl;
8687
{
8788
int ret = signal_guard(
8889
signalc_set::segmentation_fault,
89-
[]() -> int {
90+
[]() -> int
91+
{
9092
thrd_raise_signal(signalc::segmentation_fault);
9193
return 5;
9294
},
@@ -101,8 +103,9 @@ BOOST_AUTO_TEST_CASE(signal_guard / works / global, "Tests that signal_guard wor
101103
using namespace QUICKCPPLIB_NAMESPACE::signal_guard;
102104
std::cout << "1" << std::endl;
103105
jmp_buf buf;
104-
auto decider = make_signal_guard_global_decider(signalc_set::segmentation_fault | signalc_set::cxx_termination,
105-
[&buf](raised_signal_info * /*unused*/) -> bool { longjmp(buf, 78); });
106+
auto decider =
107+
make_signal_guard_global_decider(signalc_set::segmentation_fault | signalc_set::cxx_termination,
108+
[&buf](raised_signal_info * /*unused*/) -> bool { longjmp(buf, 78); });
106109
auto ret = setjmp(buf);
107110
if(!ret)
108111
{
@@ -157,7 +160,8 @@ BOOST_AUTO_TEST_CASE(signal_guard / works / watchdog, "Tests that the signal_gua
157160
}
158161

159162
// This routine is async signal safe, apart from malloc. Probably okay most of the time ?!?
160-
template <class Printer> inline void _symbolise_stack_backtrace(Printer &&print, QUICKCPPLIB_NAMESPACE::span::span<void *> bt)
163+
template <class Printer>
164+
inline void _symbolise_stack_backtrace(Printer &&print, QUICKCPPLIB_NAMESPACE::span::span<void *> bt)
161165
{
162166
#ifdef _WIN32
163167
// There isn't an implementation of backtrace_symbols_fd() for Windows, so
@@ -188,11 +192,15 @@ template <class Printer> inline void _symbolise_stack_backtrace(Printer &&print,
188192
{
189193
writeh.fd = temp[0];
190194
childwriteh.fd = temp[1];
191-
auto unmypipes = QUICKCPPLIB_NAMESPACE::scope::make_scope_exit([&]() noexcept {
195+
auto unmypipes = QUICKCPPLIB_NAMESPACE::scope::make_scope_exit(
196+
[&]() noexcept
197+
{
192198
(void) ::close(readh.fd);
193199
(void) ::close(writeh.fd);
194200
});
195-
auto unhispipes = QUICKCPPLIB_NAMESPACE::scope::make_scope_exit([&]() noexcept {
201+
auto unhispipes = QUICKCPPLIB_NAMESPACE::scope::make_scope_exit(
202+
[&]() noexcept
203+
{
196204
(void) ::close(childreadh.fd);
197205
(void) ::close(childwriteh.fd);
198206
});
@@ -202,7 +210,8 @@ template <class Printer> inline void _symbolise_stack_backtrace(Printer &&print,
202210
posix_spawn_file_actions_t child_fd_actions;
203211
if(!::posix_spawn_file_actions_init(&child_fd_actions))
204212
{
205-
auto unactions = QUICKCPPLIB_NAMESPACE::scope::make_scope_exit([&]() noexcept { ::posix_spawn_file_actions_destroy(&child_fd_actions); });
213+
auto unactions = QUICKCPPLIB_NAMESPACE::scope::make_scope_exit(
214+
[&]() noexcept { ::posix_spawn_file_actions_destroy(&child_fd_actions); });
206215
if(!::posix_spawn_file_actions_adddup2(&child_fd_actions, childreadh.fd, STDIN_FILENO))
207216
{
208217
if(!::posix_spawn_file_actions_addclose(&child_fd_actions, childreadh.fd))
@@ -214,7 +223,8 @@ template <class Printer> inline void _symbolise_stack_backtrace(Printer &&print,
214223
pid_t pid;
215224
std::vector<const char *> argptrs(2);
216225
argptrs[0] = "llvm-symbolizer";
217-
if(!::posix_spawnp(&pid, "llvm-symbolizer", &child_fd_actions, nullptr, (char **) argptrs.data(), environ))
226+
if(!::posix_spawnp(&pid, "llvm-symbolizer", &child_fd_actions, nullptr, (char **) argptrs.data(),
227+
environ))
218228
{
219229
(void) ::close(childreadh.fd);
220230
(void) ::close(childwriteh.fd);
@@ -264,7 +274,9 @@ template <class Printer> inline void _symbolise_stack_backtrace(Printer &&print,
264274
sigemptyset(&toblock);
265275
sigaddset(&toblock, SIGPIPE);
266276
pthread_sigmask(SIG_BLOCK, &toblock, &oldset);
267-
auto unsigmask = QUICKCPPLIB_NAMESPACE::scope::make_scope_exit([&toblock, &oldset]() noexcept {
277+
auto unsigmask = QUICKCPPLIB_NAMESPACE::scope::make_scope_exit(
278+
[&toblock, &oldset]() noexcept
279+
{
268280
#ifdef __APPLE__
269281
pthread_kill(pthread_self(), SIGPIPE);
270282
int cleared = 0;
@@ -305,7 +317,8 @@ template <class Printer> inline void _symbolise_stack_backtrace(Printer &&print,
305317
// We want the second line from every section separated by a double newline
306318
size_t n = 0;
307319
done = 1;
308-
auto printitem = [&](size_t idx) {
320+
auto printitem = [&](size_t idx)
321+
{
309322
print("\n ");
310323
auto idx2 = addrs.find(10, idx), idx3 = addrs.find(10, idx2 + 1);
311324
QUICKCPPLIB_NAMESPACE::string_view::string_view sv(addrs.data() + idx2 + 1, idx3 - idx2 - 1);
@@ -323,7 +336,8 @@ template <class Printer> inline void _symbolise_stack_backtrace(Printer &&print,
323336
n++;
324337
};
325338
size_t oldidx = 0;
326-
for(size_t idx = addrs.find("\n\n"); idx != std::string::npos; oldidx = idx + 2, idx = addrs.find("\n\n", idx + 1))
339+
for(size_t idx = addrs.find("\n\n"); idx != std::string::npos;
340+
oldidx = idx + 2, idx = addrs.find("\n\n", idx + 1))
327341
{
328342
printitem(oldidx);
329343
}
@@ -365,7 +379,8 @@ template <class Printer> inline void _symbolise_stack_backtrace(Printer &&print,
365379
#endif
366380
}
367381

368-
BOOST_AUTO_TEST_CASE(signal_guard / works / multithreaded, "Tests that signal_guard works as advertised across multiple threads")
382+
BOOST_AUTO_TEST_CASE(signal_guard / works / multithreaded,
383+
"Tests that signal_guard works as advertised across multiple threads")
369384
{
370385
#if QUICKCPPLIB_IN_THREAD_SANITIZER
371386
return; // hangs tsan, indeed you can't even Ctrl-C out of it!
@@ -379,22 +394,28 @@ BOOST_AUTO_TEST_CASE(signal_guard / works / multithreaded, "Tests that signal_gu
379394
static thread_local jmp_buf buf;
380395
static std::atomic<bool> done(false);
381396
auto handler = QUICKCPPLIB_NAMESPACE::signal_guard::make_signal_guard_global_decider(
382-
QUICKCPPLIB_NAMESPACE::signal_guard::signalc_set::abort_process | QUICKCPPLIB_NAMESPACE::signal_guard::signalc_set::undefined_memory_access |
383-
QUICKCPPLIB_NAMESPACE::signal_guard::signalc_set::illegal_instruction | QUICKCPPLIB_NAMESPACE::signal_guard::signalc_set::segmentation_fault |
384-
QUICKCPPLIB_NAMESPACE::signal_guard::signalc_set::floating_point_error | QUICKCPPLIB_NAMESPACE::signal_guard::signalc_set::cxx_out_of_memory |
397+
QUICKCPPLIB_NAMESPACE::signal_guard::signalc_set::abort_process |
398+
QUICKCPPLIB_NAMESPACE::signal_guard::signalc_set::undefined_memory_access |
399+
QUICKCPPLIB_NAMESPACE::signal_guard::signalc_set::illegal_instruction |
400+
QUICKCPPLIB_NAMESPACE::signal_guard::signalc_set::segmentation_fault |
401+
QUICKCPPLIB_NAMESPACE::signal_guard::signalc_set::floating_point_error |
402+
QUICKCPPLIB_NAMESPACE::signal_guard::signalc_set::cxx_out_of_memory |
385403
QUICKCPPLIB_NAMESPACE::signal_guard::signalc_set::cxx_termination,
386-
[](QUICKCPPLIB_NAMESPACE::signal_guard::raised_signal_info *rsi) -> bool {
404+
[](QUICKCPPLIB_NAMESPACE::signal_guard::raised_signal_info *rsi) -> bool
405+
{
387406
void *bt[64];
388407
auto btlen = ::backtrace(bt, 64);
389-
auto print = [](const char *s, size_t len = (size_t) -1) {
408+
auto print = [](const char *s, size_t len = (size_t) -1)
409+
{
390410
if(len == (size_t) -1)
391411
{
392412
len = strlen(s);
393413
}
394414
#ifdef _WIN32
395415
using namespace win32;
396416
unsigned long written = 0;
397-
(void) WriteFile(GetStdHandle((unsigned long) -12 /*STD_ERROR_HANDLE*/), s, (unsigned long) len, &written, nullptr);
417+
(void) WriteFile(GetStdHandle((unsigned long) -12 /*STD_ERROR_HANDLE*/), s, (unsigned long) len, &written,
418+
nullptr);
398419
#else
399420
if(-1 == ::write(2, s, len))
400421
{
@@ -403,7 +424,8 @@ BOOST_AUTO_TEST_CASE(signal_guard / works / multithreaded, "Tests that signal_gu
403424
#endif
404425
};
405426
print("FATAL: I experienced unrecoverable failure '");
406-
print(QUICKCPPLIB_NAMESPACE::signal_guard::detail::signalc_to_string(static_cast<QUICKCPPLIB_NAMESPACE::signal_guard::signalc>(rsi->signo)));
427+
print(QUICKCPPLIB_NAMESPACE::signal_guard::detail::signalc_to_string(
428+
static_cast<QUICKCPPLIB_NAMESPACE::signal_guard::signalc>(rsi->signo)));
407429
print("'. Backtrace:\n");
408430
_symbolise_stack_backtrace(print, {bt, (size_t) btlen});
409431
print("\n");
@@ -414,7 +436,9 @@ BOOST_AUTO_TEST_CASE(signal_guard / works / multithreaded, "Tests that signal_gu
414436
static std::atomic<unsigned> count(0);
415437
for(size_t n = 0; n < std::thread::hardware_concurrency(); n++)
416438
{
417-
threads.emplace_back([] {
439+
threads.emplace_back(
440+
[]
441+
{
418442
auto ret = setjmp(buf);
419443
if(!ret || ret == 10)
420444
{
@@ -445,14 +469,16 @@ BOOST_AUTO_TEST_CASE(signal_guard / works / multithreaded, "Tests that signal_gu
445469
BOOST_CHECK(count > 10);
446470
}
447471

448-
BOOST_AUTO_TEST_CASE(signal_guard / works / recursive, "Tests that signal_guard works as advertised when being recursed into across multiple threads")
472+
BOOST_AUTO_TEST_CASE(signal_guard / works / recursive,
473+
"Tests that signal_guard works as advertised when being recursed into across multiple threads")
449474
{
450475
#if QUICKCPPLIB_IN_THREAD_SANITIZER
451476
return; // hangs tsan, indeed you can't even Ctrl-C out of it!
452477
#endif
453478
static thread_local jmp_buf buf;
454479
static std::atomic<bool> done(false);
455-
static auto print = [](const char *s, size_t len = (size_t) -1) {
480+
static auto print = [](const char *s, size_t len = (size_t) -1)
481+
{
456482
if(len == (size_t) -1)
457483
{
458484
len = strlen(s);
@@ -470,19 +496,29 @@ BOOST_AUTO_TEST_CASE(signal_guard / works / recursive, "Tests that signal_guard
470496
};
471497
auto handler1 = QUICKCPPLIB_NAMESPACE::signal_guard::make_signal_guard_global_decider(
472498
QUICKCPPLIB_NAMESPACE::signal_guard::signalc_set::segmentation_fault,
473-
[](QUICKCPPLIB_NAMESPACE::signal_guard::raised_signal_info * /*unused*/) -> bool {
499+
[](QUICKCPPLIB_NAMESPACE::signal_guard::raised_signal_info * /*unused*/) -> bool
500+
{
474501
// Throw an exception within a noexcept to trigger termination
475502
print("During handle of segfault, causing floating point error\n");
476503
#ifdef _MSC_VER
477504
_controlfp(0, _MCW_EM);
478505
#else
479506
#ifdef __APPLE__
480-
auto feenableexcept = [](int excepts) {
507+
auto feenableexcept = [](int excepts)
508+
{
481509
excepts = excepts & FE_ALL_EXCEPT;
482510
fenv_t fenv;
483511
fegetenv(&fenv);
512+
#ifdef __x86_64__
484513
fenv.__control &= ~excepts;
485514
fenv.__mxcsr &= ~(excepts << 7);
515+
#elif defined(__arm__)
516+
fenv.__fpscr |= 1u << 9u; /* __fpscr_trap_enable_div_by_zero */
517+
#elif defined(__aarch64__)
518+
fenv.__fpcr |= 1u << 9u; /* __fpcr_trap_enable_div_by_zero */
519+
#else
520+
#error "Unknown platform"
521+
#endif
486522
fesetenv(&fenv);
487523
};
488524
#endif
@@ -494,7 +530,8 @@ BOOST_AUTO_TEST_CASE(signal_guard / works / recursive, "Tests that signal_guard
494530
false);
495531
auto handler2 = QUICKCPPLIB_NAMESPACE::signal_guard::make_signal_guard_global_decider(
496532
QUICKCPPLIB_NAMESPACE::signal_guard::signalc_set::floating_point_error,
497-
[](QUICKCPPLIB_NAMESPACE::signal_guard::raised_signal_info * /*unused*/) -> bool {
533+
[](QUICKCPPLIB_NAMESPACE::signal_guard::raised_signal_info * /*unused*/) -> bool
534+
{
498535
// Throw an exception within a noexcept to trigger termination
499536
print("During handle of segfault and handle of floating point error, causing out of memory\n");
500537
// new int[UINT64_MAX/sizeof(int)] does not do what I want, so ...
@@ -504,15 +541,18 @@ BOOST_AUTO_TEST_CASE(signal_guard / works / recursive, "Tests that signal_guard
504541
false);
505542
auto handler3 = QUICKCPPLIB_NAMESPACE::signal_guard::make_signal_guard_global_decider(
506543
QUICKCPPLIB_NAMESPACE::signal_guard::signalc_set::cxx_out_of_memory,
507-
[](QUICKCPPLIB_NAMESPACE::signal_guard::raised_signal_info * /*unused*/) -> bool {
544+
[](QUICKCPPLIB_NAMESPACE::signal_guard::raised_signal_info * /*unused*/) -> bool
545+
{
508546
// Throw an exception within a noexcept to trigger termination
509-
print("During handle of segfault and handle of floating point error and handle of out of memory, causing termination\n");
547+
print(
548+
"During handle of segfault and handle of floating point error and handle of out of memory, causing termination\n");
510549
std::terminate();
511550
},
512551
false);
513552
auto handler4 = QUICKCPPLIB_NAMESPACE::signal_guard::make_signal_guard_global_decider(
514553
QUICKCPPLIB_NAMESPACE::signal_guard::signalc_set::cxx_termination,
515-
[](QUICKCPPLIB_NAMESPACE::signal_guard::raised_signal_info * /*unused*/) -> bool {
554+
[](QUICKCPPLIB_NAMESPACE::signal_guard::raised_signal_info * /*unused*/) -> bool
555+
{
516556
print("Abandoning handle of termination via longjmp to restart the loop\n");
517557
longjmp(buf, 10 + done);
518558
},
@@ -521,7 +561,9 @@ BOOST_AUTO_TEST_CASE(signal_guard / works / recursive, "Tests that signal_guard
521561
static std::atomic<unsigned> count(0);
522562
for(size_t n = 0; n < std::thread::hardware_concurrency(); n++)
523563
{
524-
threads.emplace_back([] {
564+
threads.emplace_back(
565+
[]
566+
{
525567
auto ret = setjmp(buf);
526568
if(!ret || ret == 10)
527569
{
@@ -554,7 +596,8 @@ BOOST_AUTO_TEST_CASE(signal_guard / works / recursive, "Tests that signal_guard
554596
}
555597

556598

557-
BOOST_AUTO_TEST_CASE(signal_guard / performance / threadlocal, "Tests that the signal_guard has reasonable performance (thread local)")
599+
BOOST_AUTO_TEST_CASE(signal_guard / performance / threadlocal,
600+
"Tests that the signal_guard has reasonable performance (thread local)")
558601
{
559602
#if QUICKCPPLIB_IN_THREAD_SANITIZER
560603
return; // hangs tsan, indeed you can't even Ctrl-C out of it!
@@ -582,13 +625,15 @@ BOOST_AUTO_TEST_CASE(signal_guard / performance / threadlocal, "Tests that the s
582625
{
583626
uint64_t begin = ticksclock();
584627
volatile int ret = signal_guard(
585-
signalc_set::segmentation_fault, []() -> int { return 5; }, [](const raised_signal_info * /*unused*/) -> int { return 78; });
628+
signalc_set::segmentation_fault, []() -> int { return 5; },
629+
[](const raised_signal_info * /*unused*/) -> int { return 78; });
586630
uint64_t end = ticksclock();
587631
(void) ret;
588632
// std::cout << (end - begin - overhead) << std::endl;
589633
ticks += end - begin - overhead;
590634
}
591-
std::cout << "It takes " << (ticks / 128) << " CPU ticks to execute successful code (overhead was " << overhead << ")" << std::endl;
635+
std::cout << "It takes " << (ticks / 128) << " CPU ticks to execute successful code (overhead was " << overhead
636+
<< ")" << std::endl;
592637
}
593638
}
594639

0 commit comments

Comments
 (0)