debug/fpe: make tests a little more robust

We run each of the signal handler tests in their own thread so that
state is less likely to leak across tests.
This commit is contained in:
Danny Robson 2021-05-18 06:57:58 +10:00
parent 6080baa33b
commit e9a3d7d884

View File

@ -11,14 +11,14 @@
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
static int volatile fpe_value = 0; static int volatile fpe_value = 0;
static sigjmp_buf fpe_jump; static jmp_buf fpe_jump;
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
static void handle_fpe (int, siginfo_t*, void *) static void handle_fpe (int)
{ {
fpe_value = 1; fpe_value = 1;
siglongjmp (fpe_jump, 1); longjmp (fpe_jump, 1);
} }
@ -31,10 +31,7 @@ float volatile zero_val = 0.f;
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
int main () int main ()
{ {
struct sigaction fpe_sigaction {}; signal (SIGFPE, handle_fpe);
fpe_sigaction.sa_flags = SA_RESTART;
fpe_sigaction.sa_sigaction = handle_fpe;
sigaction (SIGFPE, &fpe_sigaction, nullptr);
cruft::TAP::logger tap; cruft::TAP::logger tap;
@ -67,7 +64,7 @@ int main ()
std::thread ([] () { std::thread ([] () {
cruft::debug::fpe::enable (); cruft::debug::fpe::enable ();
fpe_value = 0; fpe_value = 0;
if (!sigsetjmp (fpe_jump, 1)) if (!setjmp (fpe_jump))
cruft::debug::escape (inf_val - inf_val); cruft::debug::escape (inf_val - inf_val);
}).join (); }).join ();
tap.expect_eq (fpe_value, 1, "FE_INVALID is enabled after request"); tap.expect_eq (fpe_value, 1, "FE_INVALID is enabled after request");
@ -75,7 +72,7 @@ int main ()
std::thread ([] () { std::thread ([] () {
cruft::debug::fpe::enable (); cruft::debug::fpe::enable ();
fpe_value = 0; fpe_value = 0;
if (!sigsetjmp (fpe_jump, 1)) if (!setjmp (fpe_jump))
cruft::debug::escape (1.f / zero_val); cruft::debug::escape (1.f / zero_val);
}).join (); }).join ();
tap.expect_eq (fpe_value, 1, "FE_DIVBYZERO is enabled after request"); tap.expect_eq (fpe_value, 1, "FE_DIVBYZERO is enabled after request");
@ -83,7 +80,7 @@ int main ()
std::thread ([] () { std::thread ([] () {
fpe_value = 0; fpe_value = 0;
cruft::debug::fpe::scoped_reset resetter; cruft::debug::fpe::scoped_reset resetter;
if (!sigsetjmp (fpe_jump, 1)) if (!setjmp (fpe_jump))
cruft::debug::escape (inf_val - inf_val); cruft::debug::escape (inf_val - inf_val);
}).join (); }).join ();
tap.expect_eq (fpe_value, 0, "scoped_reset enables exceptions"); tap.expect_eq (fpe_value, 0, "scoped_reset enables exceptions");
@ -93,14 +90,14 @@ int main ()
// Do a test beforehand just in case we've forgotten to reset the // Do a test beforehand just in case we've forgotten to reset the
// fpe_value variable properly. // fpe_value variable properly.
if (!sigsetjmp (fpe_jump, 1)) if (!setjmp (fpe_jump))
cruft::debug::escape (inf_val - inf_val); cruft::debug::escape (inf_val - inf_val);
{ {
cruft::debug::fpe::scoped_reset resetter; cruft::debug::fpe::scoped_reset resetter;
} }
if (!sigsetjmp (fpe_jump, 1)) if (!setjmp (fpe_jump))
cruft::debug::escape (inf_val - inf_val); cruft::debug::escape (inf_val - inf_val);
}).join (); }).join ();
tap.expect_eq (fpe_value, 0, "scoped_reset disables exceptions"); tap.expect_eq (fpe_value, 0, "scoped_reset disables exceptions");
@ -113,7 +110,7 @@ int main ()
cruft::debug::fpe::enable (); cruft::debug::fpe::enable ();
cruft::debug::fpe::scoped_reset resetter (false); cruft::debug::fpe::scoped_reset resetter (false);
if (!sigsetjmp (fpe_jump, 1)) if (!setjmp (fpe_jump))
cruft::debug::escape (inf_val - inf_val); cruft::debug::escape (inf_val - inf_val);
}).join (); }).join ();