# HG changeset patch # User David Demelier # Date 1584013440 -3600 # Node ID 44de3c528b63fcef9f6fb2cd6fd84f65ce247c6c # Parent ebbf35d900889d78317d049dee2ff4c56dc8fb08 core: implement basic panic mechanism, continue #2484 @1h diff -r ebbf35d90088 -r 44de3c528b63 .hgignore --- a/.hgignore Wed Mar 11 20:36:10 2020 +0100 +++ b/.hgignore Thu Mar 12 12:44:00 2020 +0100 @@ -17,6 +17,7 @@ ^tests/test-error(\.exe)?$ ^tests/test-inventory(\.exe)?$ ^tests/test-map(\.exe)?$ +^tests/test-panic(\.exe)?$ ^tests/test-save(\.exe)?$ ^tests/test-script(\.exe)?$ ^tools/molko-map(\.exe)?$ diff -r ebbf35d90088 -r 44de3c528b63 Makefile --- a/Makefile Wed Mar 11 20:36:10 2020 +0100 +++ b/Makefile Thu Mar 12 12:44:00 2020 +0100 @@ -47,6 +47,7 @@ src/core/map_state.c \ src/core/message.c \ src/core/painter.c \ + src/core/panic.c \ src/core/save.c \ src/core/script.c \ src/core/sprite.c \ @@ -79,6 +80,7 @@ tests/test-error.c \ tests/test-inventory.c \ tests/test-map.c \ + tests/test-panic.c \ tests/test-save.c \ tests/test-script.c TESTS_INCS= -I extern/libgreatest -I src/core ${SDL_CFLAGS} diff -r ebbf35d90088 -r 44de3c528b63 src/core/panic.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/core/panic.c Thu Mar 12 12:44:00 2020 +0100 @@ -0,0 +1,46 @@ +/* + * panic.c -- unrecoverable error handling + * + * Copyright (c) 2020 David Demelier + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include + +#include "error.h" +#include "panic.h" + +void (*panic_handler)(void) = error_fatal; + +void +panic(const char *fmt, ...) +{ + assert(fmt); + + va_list ap; + + va_start(ap, fmt); + panicv(fmt, ap); + va_end(ap); +} + +void +panicv(const char *fmt, va_list ap) +{ + assert(fmt); + assert(panic_handler); + + error_vprintf(fmt, ap); + panic_handler(); +} diff -r ebbf35d90088 -r 44de3c528b63 src/core/panic.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/core/panic.h Thu Mar 12 12:44:00 2020 +0100 @@ -0,0 +1,72 @@ +/* + * panic.h -- unrecoverable error handling + * + * Copyright (c) 2020 David Demelier + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef MOLKO_PANIC_H +#define MOLKO_PANIC_H + +/** + * \file panic.h + * \brief Unrecoverable error handling. + * \ingroup basics + * + * This set of functions should be used to detect runtime errors that are + * unexpected. They should be used only when the game cannot continue because + * it is in a unrecoverable state. + * + * Examples of appropriate use cases: + * + * - Game saved data is corrupt, + * - Assets are missing, + * - No more memory. + * + * In other contexts, use asserts to indicates programming error and + * appropriate solutions to recover the game otherwise. + */ + +#include + +/** + * \brief Global panic handler. + * + * The default implementation shows the last error and exit with code 1. + */ +extern void (*panic_handler)(void); + +/** + * Terminate the program using the \ref panic_handler routine. + * + * This function will first set the global error with the provided format + * string and then call the handler. + * + * \pre fmt != NULL + * \param fmt the printf(3) format string + */ +void +panic(const char *fmt, ...); + +/** + * Similar to \ref panic but with a va_list argument instead. + * + * \pre fmt != NULL + * \param fmt the printf(3) format string + * \param ap the arguments pointer + */ +void +panicv(const char *fmt, va_list ap); + +#endif /* !MOLKO_PANIC_H */ diff -r ebbf35d90088 -r 44de3c528b63 src/core/util.c --- a/src/core/util.c Wed Mar 11 20:36:10 2020 +0100 +++ b/src/core/util.c Thu Mar 12 12:44:00 2020 +0100 @@ -22,8 +22,8 @@ #include +#include "panic.h" #include "util.h" -#include "error.h" void * emalloc(size_t size) @@ -31,7 +31,7 @@ void *mem; if (!(mem = malloc(size))) - error_fatalf("%s\n", strerror(errno)); + panic("%s\n", strerror(errno)); return mem; } @@ -42,7 +42,7 @@ void *mem; if (!(mem = calloc(n, size))) - error_fatalf("%s\n", strerror(errno)); + panic("%s\n", strerror(errno)); return mem; } @@ -53,7 +53,7 @@ void *mem; if (!(mem = malloc(size))) - error_fatalf("%s\n", strerror(errno)); + panic("%s\n", strerror(errno)); return memcpy(mem, ptr, size); } diff -r ebbf35d90088 -r 44de3c528b63 tests/test-panic.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/test-panic.c Thu Mar 12 12:44:00 2020 +0100 @@ -0,0 +1,60 @@ +/* + * test-panic.c -- test panic routines + * + * Copyright (c) 2020 David Demelier + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include + +#define GREATEST_USE_ABBREVS 0 +#include + +#include +#include + +static bool handler_called; + +static void +handler(void) +{ + handler_called = true; +} + +GREATEST_TEST +basics_simple(void) +{ + panic_handler = handler; + handler_called = false; + + panic("this is an error"); + GREATEST_ASSERT(handler_called); + GREATEST_ASSERT_STR_EQ(error(), "this is an error"); + GREATEST_PASS(); +} + +GREATEST_SUITE(basics) +{ + GREATEST_RUN_TEST(basics_simple); +} + +GREATEST_MAIN_DEFS(); + +int +main(int argc, char **argv) +{ + GREATEST_MAIN_BEGIN(); + GREATEST_RUN_SUITE(basics); + GREATEST_MAIN_END(); +}