On Thu, 21 Dec 2023, Rémi Denis-Courmont wrote:

diff --git a/tests/checkasm/checkasm.c b/tests/checkasm/checkasm.c
index 6318d9296b..668034c67f 100644
--- a/tests/checkasm/checkasm.c
+++ b/tests/checkasm/checkasm.c
@@ -23,8 +23,10 @@
#include "config.h"
#include "config_components.h"

-#ifndef _GNU_SOURCE
-# define _GNU_SOURCE // for syscall (performance monitoring API), strsignal()
+#if CONFIG_LINUX_PERF
+# ifndef _GNU_SOURCE
+#  define _GNU_SOURCE // for syscall (performance monitoring API)
+# endif
#endif

#include <signal.h>
@@ -326,6 +328,7 @@ static struct {
    const char *cpu_flag_name;
    const char *test_name;
    int verbose;
+    int catch_signals;
} state;

/* PRNG state */
@@ -627,6 +630,64 @@ static CheckasmFunc *get_func(CheckasmFunc **root, const 
char *name)
    return f;
}

+checkasm_context checkasm_context_buf;
+
+/* Crash handling: attempt to catch crashes and handle them
+ * gracefully instead of just aborting abruptly. */
+#ifdef _WIN32
+#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
+static LONG NTAPI signal_handler(EXCEPTION_POINTERS *const e) {
+    const char *err;
+
+    if (!state.catch_signals)
+        return EXCEPTION_CONTINUE_SEARCH;
+
+    switch (e->ExceptionRecord->ExceptionCode) {
+    case EXCEPTION_FLT_DIVIDE_BY_ZERO:
+    case EXCEPTION_INT_DIVIDE_BY_ZERO:
+        err = "fatal arithmetic error";
+        break;
+    case EXCEPTION_ILLEGAL_INSTRUCTION:
+    case EXCEPTION_PRIV_INSTRUCTION:
+        err = "illegal instruction";
+        break;
+    case EXCEPTION_ACCESS_VIOLATION:
+    case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
+    case EXCEPTION_DATATYPE_MISALIGNMENT:
+    case EXCEPTION_STACK_OVERFLOW:
+        err = "segmentation fault";
+        break;
+    case EXCEPTION_IN_PAGE_ERROR:
+        err = "bus error";
+        break;
+    default:
+        return EXCEPTION_CONTINUE_SEARCH;
+    }
+    state.catch_signals = 0;
+    checkasm_fail_func("%s", err);
+    checkasm_load_context();
+    return EXCEPTION_CONTINUE_EXECUTION; /* never reached, but shuts up gcc */
+}
+#endif
+#else
+static void signal_handler(const int s) {
+    if (state.catch_signals) {
+        state.catch_signals = 0;
+        checkasm_fail_func("%s",
+                           s == SIGFPE ? "fatal arithmetic error" :
+                           s == SIGILL ? "illegal instruction" :
+                           s == SIGBUS ? "bus error" :
+                                         "segmentation fault");
+        checkasm_load_context();

Use of format string is probably not async-signal-safe.

I'll have a look if it's possible to restructure this into doing the checkasm_fail_func call afterwards.

I would also be surprised if the load_context() function was safe in signal context. That's why the current code does pretty much nothing other than a long jump.

The load_context() function here is either longjmp or RtlRestoreContext.

// Martin
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".

Reply via email to