diff --git a/api/arch.hpp b/api/arch.hpp index c5b72b49e..19c818580 100644 --- a/api/arch.hpp +++ b/api/arch.hpp @@ -27,8 +27,8 @@ #include -extern void __arch_poweroff(); -extern void __arch_reboot(); +[[noreturn]] extern void __arch_poweroff(); +[[noreturn]] extern void __arch_reboot(); extern void __arch_enable_legacy_irq(uint8_t); extern void __arch_disable_legacy_irq(uint8_t); extern void __arch_system_deactivate(); diff --git a/api/expects b/api/expects index 9ff218539..b030711b5 100644 --- a/api/expects +++ b/api/expects @@ -32,18 +32,34 @@ #endif #include +#include + +inline bool __expect_is_recursive() { +#ifndef UNITTESTS + static volatile bool in_failure = false; + if (in_failure) return true; + in_failure = true; + return false; +#else + return false; +#endif +} + inline void __expect_emit_failure(std::string_view msg, std::string_view panic_text) { #ifndef UNITTESTS + #ifdef INCLUDEOS_SMP_ENABLE SMP::global_lock(); #endif + std::fprintf(stderr, "%.*s\n", int(msg.size()), msg.data()); fflush(NULL); #ifdef INCLUDEOS_SMP_ENABLE SMP::global_unlock(); #endif os::panic(std::string(panic_text).c_str()); -#else // TEST + +#else // UNITTESTS (void) panic_text; // throw here to allow tests to capture the error #include @@ -52,13 +68,36 @@ inline void __expect_emit_failure(std::string_view msg, std::string_view panic_t } template -inline void __expect_failf(const char *err_prefix, const char * /*cond*/, const char *file, int line, const char *func, std::format_string fmt, Args&&... args){ +inline void __expect_failf(const char *err_prefix, const char * cond, const char *file, int line, const char *func, std::format_string fmt, Args&&... args){ + if (__expect_is_recursive()) { + kprint("Fatal Expects/Ensures recursion. (libc not initialized?)\n"); + + kprint("Condition was '"); + kprint(cond); kprint("' @ "); + kprint(file); kprint(":"); + kprint(func); kprint(" with fmt="); + kprint(fmt.get().data()); kprint("\n"); + + // os::shutdown(); + __arch_poweroff(); + } auto reason_msg = std::format(fmt, std::forward(args)...); auto error_msg = std::format("{}:{}:{}: {}: {}", file, line, func, err_prefix, reason_msg); __expect_emit_failure(error_msg, reason_msg); } inline void __expect_failf(const char *err_prefix, const char *cond, const char *file, int line, const char *func){ + if (__expect_is_recursive()) { + kprint("Fatal Expects/Ensures recursion (libc not initialized?)\n"); + + kprint("Condition was '"); + kprint(cond); kprint("' @ "); + kprint(file); kprint(":"); + kprint(func); kprint("\n"); + + // os::shutdown(); + __arch_poweroff(); + } auto reason_msg = std::format("{}: {}", err_prefix, cond); auto error_msg = std::format("{}:{}:{}: {}", file, line, func, err_prefix); __expect_emit_failure(error_msg, reason_msg); diff --git a/api/os.hpp b/api/os.hpp index 827d71c68..255724497 100644 --- a/api/os.hpp +++ b/api/os.hpp @@ -86,7 +86,7 @@ namespace os { // /** Trigger unrecoverable error and output diagnostics **/ - __attribute__((noreturn)) + [[noreturn]] void panic(const char* why) noexcept; /** Default behavior after panic **/ diff --git a/src/kernel/syscalls.cpp b/src/kernel/syscalls.cpp index b7b555dbd..59932efc9 100644 --- a/src/kernel/syscalls.cpp +++ b/src/kernel/syscalls.cpp @@ -118,12 +118,16 @@ extern kernel::ctor_t __plugin_ctors_end; * Print EOT character to stderr, to signal outside that PANIC output completed * If the handler returns, go to (permanent) sleep **/ -void os::panic(const char* why) noexcept +[[noreturn]] void os::panic(const char* why) noexcept { cpu_enable_panicking(); if (kernel::panics() > 4) double_fault(why); const int current_cpu = SMP::cpu_id(); + if (!kernel::libc_initialized()) { + kprint("FATAL: panic before libc\n"); + panic_epilogue(why); + } #ifdef INCLUDEOS_SMP_ENABLE SMP::global_lock(); diff --git a/src/platform/x86_pc/acpi.cpp b/src/platform/x86_pc/acpi.cpp index 5ea85789c..e110eff0d 100644 --- a/src/platform/x86_pc/acpi.cpp +++ b/src/platform/x86_pc/acpi.cpp @@ -393,8 +393,7 @@ namespace x86 { } } - __attribute__((noreturn)) - void ACPI::shutdown() + [[noreturn]] void ACPI::shutdown() { asm("cli"); diff --git a/src/platform/x86_pc/acpi.hpp b/src/platform/x86_pc/acpi.hpp index 68f387166..687847b20 100644 --- a/src/platform/x86_pc/acpi.hpp +++ b/src/platform/x86_pc/acpi.hpp @@ -102,7 +102,7 @@ namespace x86 { } static void reboot(); - static void shutdown(); + [[noreturn]] static void shutdown(); private: void discover(); diff --git a/src/platform/x86_pc/platform.cpp b/src/platform/x86_pc/platform.cpp index 15ef03787..3a720d030 100644 --- a/src/platform/x86_pc/platform.cpp +++ b/src/platform/x86_pc/platform.cpp @@ -147,12 +147,11 @@ void __arch_disable_legacy_irq(uint8_t irq) x86::APIC::disable_irq(irq); } -void __arch_poweroff() +[[noreturn]] void __arch_poweroff() { x86::ACPI::shutdown(); - __builtin_unreachable(); } -void __arch_reboot() +[[noreturn]] void __arch_reboot() { x86::ACPI::reboot(); __builtin_unreachable();