From d930d3f5bf77323378c25bb5000f0962aedbb618 Mon Sep 17 00:00:00 2001 From: "Bjoern Ganster (on Windows)" Date: Tue, 1 Jul 2025 14:55:37 +0200 Subject: [PATCH 1/3] Add a callback that will be called just before abort. This allows apps without a console to display a message to the user and save data if needed. --- ggml/include/ggml.h | 6 ++++++ ggml/src/ggml.c | 21 +++++++++++++++++---- 2 files changed, 23 insertions(+), 4 deletions(-) diff --git a/ggml/include/ggml.h b/ggml/include/ggml.h index f8238f3159b9f..c78e26528adb2 100644 --- a/ggml/include/ggml.h +++ b/ggml/include/ggml.h @@ -314,6 +314,12 @@ extern "C" { #endif + // Function type used in fatal error callbacks + typedef void (*ggml_abort_callback_t)(const char * error_message); + + // Set the abort callback (passing null will restore original abort functionality: printing a message to stdout) + GGML_API void ggml_set_abort_callback(ggml_abort_callback_t callback); + GGML_NORETURN GGML_ATTRIBUTE_FORMAT(3, 4) GGML_API void ggml_abort(const char * file, int line, const char * fmt, ...); diff --git a/ggml/src/ggml.c b/ggml/src/ggml.c index c51cb57cc6821..475942bba92ed 100644 --- a/ggml/src/ggml.c +++ b/ggml/src/ggml.c @@ -202,19 +202,32 @@ void ggml_print_backtrace(void) { } #endif +static ggml_abort_callback_t g_abort_callback = NULL; + +// Set the abort callback (passing null will restore original abort functionality: printing a message to stdout) +GGML_API void ggml_set_abort_callback(ggml_abort_callback_t callback) { + g_abort_callback = callback; +} + void ggml_abort(const char * file, int line, const char * fmt, ...) { fflush(stdout); - fprintf(stderr, "%s:%d: ", file, line); + char message[2048]; + int offset = snprintf(message, sizeof(message), "%s:%d: ", file, line); va_list args; va_start(args, fmt); - vfprintf(stderr, fmt, args); + vsnprintf(message + offset, sizeof(message) - offset, fmt, args); va_end(args); - fprintf(stderr, "\n"); + if (g_abort_callback) { + g_abort_callback(message); + } else { + // default: print to stderr and abort + fprintf(stderr, "%s\n", message); + ggml_print_backtrace(); + } - ggml_print_backtrace(); abort(); } From 9d34d8c81b2b0c872cf3e032ab45656565c430da Mon Sep 17 00:00:00 2001 From: "Bjoern Ganster (on Windows)" Date: Tue, 1 Jul 2025 19:54:57 +0200 Subject: [PATCH 2/3] Return previous callback to allow callback chaining --- ggml/include/ggml.h | 3 ++- ggml/src/ggml.c | 4 +++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/ggml/include/ggml.h b/ggml/include/ggml.h index c78e26528adb2..ec5478db8c8df 100644 --- a/ggml/include/ggml.h +++ b/ggml/include/ggml.h @@ -318,7 +318,8 @@ extern "C" { typedef void (*ggml_abort_callback_t)(const char * error_message); // Set the abort callback (passing null will restore original abort functionality: printing a message to stdout) - GGML_API void ggml_set_abort_callback(ggml_abort_callback_t callback); + // Returns the old callback for chaining + GGML_API ggml_abort_callback_t ggml_set_abort_callback(ggml_abort_callback_t callback); GGML_NORETURN GGML_ATTRIBUTE_FORMAT(3, 4) GGML_API void ggml_abort(const char * file, int line, const char * fmt, ...); diff --git a/ggml/src/ggml.c b/ggml/src/ggml.c index 475942bba92ed..86ca80b5c39dc 100644 --- a/ggml/src/ggml.c +++ b/ggml/src/ggml.c @@ -205,8 +205,10 @@ void ggml_print_backtrace(void) { static ggml_abort_callback_t g_abort_callback = NULL; // Set the abort callback (passing null will restore original abort functionality: printing a message to stdout) -GGML_API void ggml_set_abort_callback(ggml_abort_callback_t callback) { +GGML_API ggml_abort_callback_t ggml_set_abort_callback(ggml_abort_callback_t callback) { + ggml_abort_callback_t retVal = g_abort_callback; g_abort_callback = callback; + return retVal; } void ggml_abort(const char * file, int line, const char * fmt, ...) { From 9f46e41b1b8da675100ba6d957c406d6410c8fe2 Mon Sep 17 00:00:00 2001 From: Diego Devesa Date: Tue, 1 Jul 2025 22:59:08 +0200 Subject: [PATCH 3/3] style fixes --- ggml/src/ggml.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/ggml/src/ggml.c b/ggml/src/ggml.c index 86ca80b5c39dc..4227fb101f09a 100644 --- a/ggml/src/ggml.c +++ b/ggml/src/ggml.c @@ -206,16 +206,16 @@ static ggml_abort_callback_t g_abort_callback = NULL; // Set the abort callback (passing null will restore original abort functionality: printing a message to stdout) GGML_API ggml_abort_callback_t ggml_set_abort_callback(ggml_abort_callback_t callback) { - ggml_abort_callback_t retVal = g_abort_callback; + ggml_abort_callback_t ret_val = g_abort_callback; g_abort_callback = callback; - return retVal; + return ret_val; } void ggml_abort(const char * file, int line, const char * fmt, ...) { fflush(stdout); char message[2048]; - int offset = snprintf(message, sizeof(message), "%s:%d: ", file, line); + int offset = snprintf(message, sizeof(message), "%s:%d: ", file, line); va_list args; va_start(args, fmt); @@ -225,7 +225,7 @@ void ggml_abort(const char * file, int line, const char * fmt, ...) { if (g_abort_callback) { g_abort_callback(message); } else { - // default: print to stderr and abort + // default: print error and backtrace to stderr fprintf(stderr, "%s\n", message); ggml_print_backtrace(); }