From 5a746cad817d0c732c76387d88a476ec5df4aaf5 Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Mon, 7 Oct 2019 16:44:27 +0200 Subject: [PATCH] Always abort on DDS_FATAL variants + test (#270) The test only works on Linux and macOS because of the system dependencies in catching an abort. The logging code is platform independent so testing only on these platforms still gives a good sanity check. Signed-off-by: Erik Boasson --- src/ddsrt/src/log.c | 2 +- src/ddsrt/tests/log.c | 104 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 105 insertions(+), 1 deletion(-) diff --git a/src/ddsrt/src/log.c b/src/ddsrt/src/log.c index e384c55..a988c92 100644 --- a/src/ddsrt/src/log.c +++ b/src/ddsrt/src/log.c @@ -64,7 +64,7 @@ static void default_sink (void *ptr, const dds_log_data_t *data) static struct ddsrt_log_cfg_impl logconfig = { .c = { - .mask = DDS_LC_ERROR | DDS_LC_WARNING, + .mask = DDS_LC_ERROR | DDS_LC_WARNING | DDS_LC_FATAL, .tracemask = 0, .domid = UINT32_MAX }, diff --git a/src/ddsrt/tests/log.c b/src/ddsrt/tests/log.c index 43ccf8e..5a0facd 100644 --- a/src/ddsrt/tests/log.c +++ b/src/ddsrt/tests/log.c @@ -20,6 +20,7 @@ #endif /* __APPLE__ */ #include "CUnit/Test.h" +#include "CUnit/Theory.h" #include "dds/ddsrt/heap.h" #include "dds/ddsrt/log.h" #include "dds/ddsrt/misc.h" @@ -403,3 +404,106 @@ CU_Test(dds_log, synchronous_sink_changes, .fini=reset) CU_ASSERT(arg.after < dds_time()); #endif } + +/* Sanity checks that FATAL calls abort() -- this is very much platform + dependent code, so we only do it on Linux and macOS, assuming that + the logging implementation doesn't make any distinction between different + platforms and that abort() is correctly implemented by the C library. + + macOS: abort causes abnormal termination unless the handler doesn't return, + hence the setjmp/longjmp. */ +#if defined __linux || defined __APPLE__ +#define TEST_DDS_LC_FATAL 1 +#else +#define TEST_DDS_LC_FATAL 0 +#endif + +#if TEST_DDS_LC_FATAL +#include + +static sigjmp_buf abort_jmpbuf; +static char abort_message[100]; +static char abort_message_trace[100]; +static ddsrt_log_cfg_t abort_logconfig; + +static void abort_handler (int sig) +{ + (void) sig; + siglongjmp (abort_jmpbuf, 1); +} + +static void abort_log (void *arg, const dds_log_data_t *info) +{ + (void) arg; + ddsrt_strlcpy (abort_message, info->message, sizeof (abort_message)); +} + +static void abort_trace (void *arg, const dds_log_data_t *info) +{ + (void) arg; + ddsrt_strlcpy (abort_message_trace, info->message, sizeof (abort_message_trace)); +} + +CU_TheoryDataPoints(dds_log, fatal_aborts) = { + CU_DataPoints(bool, false, false, false, true, true, true), /* global/config */ + CU_DataPoints(int, 0, 1, 2, 0, 1, 2), /* mask init mode */ + CU_DataPoints(bool, false, false, true, false, false, true) /* expect in trace? */ +}; +#else +CU_TheoryDataPoints(dds_log, fatal_aborts) = { + CU_DataPoints(bool, false), /* global/config */ + CU_DataPoints(int, 0), /* mask init mode */ + CU_DataPoints(bool, false) /* expect in trace? */ +}; +#endif + +CU_Theory((bool local, int mode, bool expect_in_trace), dds_log, fatal_aborts) +{ +#if TEST_DDS_LC_FATAL + struct sigaction action, oldaction; + action.sa_flags = 0; + action.sa_handler = abort_handler; + + if (sigsetjmp (abort_jmpbuf, 0) != 0) + { + sigaction (SIGABRT, &oldaction, NULL); + CU_ASSERT_STRING_EQUAL (abort_message, "oops\n"); + CU_ASSERT_STRING_EQUAL (abort_message_trace, expect_in_trace ? "oops\n" : ""); + } + else + { + memset (abort_message, 0, sizeof (abort_message)); + memset (abort_message_trace, 0, sizeof (abort_message_trace)); + dds_set_log_sink (abort_log, NULL); + dds_set_trace_sink (abort_trace, NULL); + sigaction (SIGABRT, &action, &oldaction); + if (local) + { + switch (mode) + { + case 0: + /* FALL THROUGH */ + case 1: dds_log_cfg_init (&abort_logconfig, 0, 0, 0, 0); break; + case 2: dds_log_cfg_init (&abort_logconfig, 0, DDS_LC_TRACE, 0, 0); break; + } + DDS_CLOG (DDS_LC_FATAL, &abort_logconfig, "oops\n"); + } + else + { + switch (mode) + { + case 0: break; + case 1: dds_set_log_mask (0); break; + case 2: dds_set_log_mask (DDS_LC_TRACE); break; + } + DDS_FATAL ("oops\n"); + } + sigaction (SIGABRT, &oldaction, NULL); + CU_ASSERT (0); + } +#else + (void) local; + (void) mode; + (void) expect_in_trace; +#endif +}