changeset 88:44de3c528b63

core: implement basic panic mechanism, continue #2484 @1h
author David Demelier <markand@malikania.fr>
date Thu, 12 Mar 2020 12:44:00 +0100
parents ebbf35d90088
children 30baadb6f6a2
files .hgignore Makefile src/core/panic.c src/core/panic.h src/core/util.c tests/test-panic.c
diffstat 6 files changed, 185 insertions(+), 4 deletions(-) [+]
line wrap: on
line diff
--- 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)?$
--- 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}
--- /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 <markand@malikania.fr>
+ *
+ * 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 <assert.h>
+
+#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();
+}
--- /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 <markand@malikania.fr>
+ *
+ * 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 <stdarg.h>
+
+/**
+ * \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 */
--- 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 <SDL.h>
 
+#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);
 }
--- /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 <markand@malikania.fr>
+ *
+ * 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 <stdbool.h>
+
+#define GREATEST_USE_ABBREVS 0
+#include <greatest.h>
+
+#include <error.h>
+#include <panic.h>
+
+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();
+}