@@ -79,14 +79,16 @@ BOOST_AUTO_TEST_CASE(signal_guard / works / threadlocal, "Tests that signal_guar
79
79
std::cout << " 2" << std::endl;
80
80
{
81
81
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 ; });
83
84
BOOST_CHECK (ret == 78 );
84
85
}
85
86
std::cout << " 3" << std::endl;
86
87
{
87
88
int ret = signal_guard (
88
89
signalc_set::segmentation_fault,
89
- []() -> int {
90
+ []() -> int
91
+ {
90
92
thrd_raise_signal (signalc::segmentation_fault);
91
93
return 5 ;
92
94
},
@@ -101,8 +103,9 @@ BOOST_AUTO_TEST_CASE(signal_guard / works / global, "Tests that signal_guard wor
101
103
using namespace QUICKCPPLIB_NAMESPACE ::signal_guard;
102
104
std::cout << " 1" << std::endl;
103
105
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 ); });
106
109
auto ret = setjmp (buf);
107
110
if (!ret)
108
111
{
@@ -157,7 +160,8 @@ BOOST_AUTO_TEST_CASE(signal_guard / works / watchdog, "Tests that the signal_gua
157
160
}
158
161
159
162
// 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)
161
165
{
162
166
#ifdef _WIN32
163
167
// 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,
188
192
{
189
193
writeh.fd = temp[0 ];
190
194
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
+ {
192
198
(void ) ::close (readh.fd );
193
199
(void ) ::close (writeh.fd );
194
200
});
195
- auto unhispipes = QUICKCPPLIB_NAMESPACE::scope::make_scope_exit ([&]() noexcept {
201
+ auto unhispipes = QUICKCPPLIB_NAMESPACE::scope::make_scope_exit (
202
+ [&]() noexcept
203
+ {
196
204
(void ) ::close (childreadh.fd );
197
205
(void ) ::close (childwriteh.fd );
198
206
});
@@ -202,7 +210,8 @@ template <class Printer> inline void _symbolise_stack_backtrace(Printer &&print,
202
210
posix_spawn_file_actions_t child_fd_actions;
203
211
if (!::posix_spawn_file_actions_init (&child_fd_actions))
204
212
{
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); });
206
215
if (!::posix_spawn_file_actions_adddup2 (&child_fd_actions, childreadh.fd , STDIN_FILENO))
207
216
{
208
217
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,
214
223
pid_t pid;
215
224
std::vector<const char *> argptrs (2 );
216
225
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))
218
228
{
219
229
(void ) ::close (childreadh.fd );
220
230
(void ) ::close (childwriteh.fd );
@@ -264,7 +274,9 @@ template <class Printer> inline void _symbolise_stack_backtrace(Printer &&print,
264
274
sigemptyset (&toblock);
265
275
sigaddset (&toblock, SIGPIPE);
266
276
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
+ {
268
280
#ifdef __APPLE__
269
281
pthread_kill (pthread_self (), SIGPIPE);
270
282
int cleared = 0 ;
@@ -305,7 +317,8 @@ template <class Printer> inline void _symbolise_stack_backtrace(Printer &&print,
305
317
// We want the second line from every section separated by a double newline
306
318
size_t n = 0 ;
307
319
done = 1 ;
308
- auto printitem = [&](size_t idx) {
320
+ auto printitem = [&](size_t idx)
321
+ {
309
322
print (" \n " );
310
323
auto idx2 = addrs.find (10 , idx), idx3 = addrs.find (10 , idx2 + 1 );
311
324
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,
323
336
n++;
324
337
};
325
338
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 ))
327
341
{
328
342
printitem (oldidx);
329
343
}
@@ -365,7 +379,8 @@ template <class Printer> inline void _symbolise_stack_backtrace(Printer &&print,
365
379
#endif
366
380
}
367
381
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" )
369
384
{
370
385
#if QUICKCPPLIB_IN_THREAD_SANITIZER
371
386
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
379
394
static thread_local jmp_buf buf;
380
395
static std::atomic<bool > done (false );
381
396
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 |
385
403
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
+ {
387
406
void *bt[64 ];
388
407
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
+ {
390
410
if (len == (size_t ) -1 )
391
411
{
392
412
len = strlen (s);
393
413
}
394
414
#ifdef _WIN32
395
415
using namespace win32 ;
396
416
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 );
398
419
#else
399
420
if (-1 == ::write (2 , s, len))
400
421
{
@@ -403,7 +424,8 @@ BOOST_AUTO_TEST_CASE(signal_guard / works / multithreaded, "Tests that signal_gu
403
424
#endif
404
425
};
405
426
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 )));
407
429
print (" '. Backtrace:\n " );
408
430
_symbolise_stack_backtrace (print, {bt, (size_t ) btlen});
409
431
print (" \n " );
@@ -414,7 +436,9 @@ BOOST_AUTO_TEST_CASE(signal_guard / works / multithreaded, "Tests that signal_gu
414
436
static std::atomic<unsigned > count (0 );
415
437
for (size_t n = 0 ; n < std::thread::hardware_concurrency (); n++)
416
438
{
417
- threads.emplace_back ([] {
439
+ threads.emplace_back (
440
+ []
441
+ {
418
442
auto ret = setjmp (buf);
419
443
if (!ret || ret == 10 )
420
444
{
@@ -445,14 +469,16 @@ BOOST_AUTO_TEST_CASE(signal_guard / works / multithreaded, "Tests that signal_gu
445
469
BOOST_CHECK (count > 10 );
446
470
}
447
471
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" )
449
474
{
450
475
#if QUICKCPPLIB_IN_THREAD_SANITIZER
451
476
return ; // hangs tsan, indeed you can't even Ctrl-C out of it!
452
477
#endif
453
478
static thread_local jmp_buf buf;
454
479
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
+ {
456
482
if (len == (size_t ) -1 )
457
483
{
458
484
len = strlen (s);
@@ -470,19 +496,29 @@ BOOST_AUTO_TEST_CASE(signal_guard / works / recursive, "Tests that signal_guard
470
496
};
471
497
auto handler1 = QUICKCPPLIB_NAMESPACE::signal_guard::make_signal_guard_global_decider (
472
498
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
+ {
474
501
// Throw an exception within a noexcept to trigger termination
475
502
print (" During handle of segfault, causing floating point error\n " );
476
503
#ifdef _MSC_VER
477
504
_controlfp (0 , _MCW_EM);
478
505
#else
479
506
#ifdef __APPLE__
480
- auto feenableexcept = [](int excepts) {
507
+ auto feenableexcept = [](int excepts)
508
+ {
481
509
excepts = excepts & FE_ALL_EXCEPT;
482
510
fenv_t fenv;
483
511
fegetenv (&fenv);
512
+ #ifdef __x86_64__
484
513
fenv.__control &= ~excepts;
485
514
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
486
522
fesetenv (&fenv);
487
523
};
488
524
#endif
@@ -494,7 +530,8 @@ BOOST_AUTO_TEST_CASE(signal_guard / works / recursive, "Tests that signal_guard
494
530
false );
495
531
auto handler2 = QUICKCPPLIB_NAMESPACE::signal_guard::make_signal_guard_global_decider (
496
532
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
+ {
498
535
// Throw an exception within a noexcept to trigger termination
499
536
print (" During handle of segfault and handle of floating point error, causing out of memory\n " );
500
537
// 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
504
541
false );
505
542
auto handler3 = QUICKCPPLIB_NAMESPACE::signal_guard::make_signal_guard_global_decider (
506
543
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
+ {
508
546
// 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 " );
510
549
std::terminate ();
511
550
},
512
551
false );
513
552
auto handler4 = QUICKCPPLIB_NAMESPACE::signal_guard::make_signal_guard_global_decider (
514
553
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
+ {
516
556
print (" Abandoning handle of termination via longjmp to restart the loop\n " );
517
557
longjmp (buf, 10 + done);
518
558
},
@@ -521,7 +561,9 @@ BOOST_AUTO_TEST_CASE(signal_guard / works / recursive, "Tests that signal_guard
521
561
static std::atomic<unsigned > count (0 );
522
562
for (size_t n = 0 ; n < std::thread::hardware_concurrency (); n++)
523
563
{
524
- threads.emplace_back ([] {
564
+ threads.emplace_back (
565
+ []
566
+ {
525
567
auto ret = setjmp (buf);
526
568
if (!ret || ret == 10 )
527
569
{
@@ -554,7 +596,8 @@ BOOST_AUTO_TEST_CASE(signal_guard / works / recursive, "Tests that signal_guard
554
596
}
555
597
556
598
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)" )
558
601
{
559
602
#if QUICKCPPLIB_IN_THREAD_SANITIZER
560
603
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
582
625
{
583
626
uint64_t begin = ticksclock ();
584
627
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 ; });
586
630
uint64_t end = ticksclock ();
587
631
(void ) ret;
588
632
// std::cout << (end - begin - overhead) << std::endl;
589
633
ticks += end - begin - overhead;
590
634
}
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;
592
637
}
593
638
}
594
639
0 commit comments