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(); diff --git a/test/integration/kernel/kprint/test.py b/test/integration/kernel/kprint/test.py index 1a2ec699c..079fd36e7 100755 --- a/test/integration/kernel/kprint/test.py +++ b/test/integration/kernel/kprint/test.py @@ -3,7 +3,6 @@ from __future__ import division from __future__ import print_function from builtins import str -from past.utils import old_div import sys import os @@ -27,7 +26,7 @@ def set_format_string_size(line): def check_truncation(line): assert(format_string_size) - print("Received truncated string: ", line, "of size", len(line), "(format size * ", old_div(len(line),format_string_size),")") + print("Received truncated string: ", line, "of size", len(line), "(format size * ", len(line)//format_string_size,")") assert(len(line) <= format_string_size * 2) # truncated outputs are unacceptable :) assert(line.strip().split(" ")[-1] == "END") diff --git a/test/integration/net/http/test.py b/test/integration/net/http/test.py index 5e0d61429..8e31b5ec0 100755 --- a/test/integration/net/http/test.py +++ b/test/integration/net/http/test.py @@ -1,19 +1,17 @@ #!/usr/bin/env python3 -from future import standard_library -standard_library.install_aliases() -from builtins import str -import sys -import os import _thread +import http.server +import sys +import urllib.error +import urllib.parse +import urllib.request from vmrunner import vmrunner HOST = '' PORT = 9011 -import http.server - DO_SERVE = True class RequestHandler(http.server.BaseHTTPRequestHandler): def do_GET(s): @@ -36,7 +34,6 @@ def Client_test(): _thread.start_new_thread(Client_test, ()) -import urllib.request, urllib.error, urllib.parse def Server_test(triggerline): res = urllib.request.urlopen("http://10.0.0.46:8080").read() assert(res.decode('utf-8') == "Hello")