From 852ab79359b6f594e9cc75d73915688458fc56a3 Mon Sep 17 00:00:00 2001 From: Norman Feske Date: Mon, 17 Aug 2020 16:23:48 +0200 Subject: [PATCH] Move atexit handling from base lib to libc This patch untangles the interplay of the base library and the libc during the exit handling. - The CXA ABI for the atexit handling is now provided by the libc. For plain Genode components without libc dependency, __cxa_atexit is a no-op, which is consistent with Genode's notion of components. - The 'abort' implementation of the base library no longer calls 'genode_exit' but merely 'sleep_forever'. This way, the cxx library no longer depends on a 'genode_exit' implementation. - The libc provides 'atexit' support by storing metadata on the libc kernel's heap now, thereby eliminating the former bounded maximum number of atexit handlers. - Shared-library dtors are no longer called via the atexit mechanism by explicitly by the dynamic linker. This slightly changes the call order of destructors (adjustment of the ldso test). Functions marked as destructors are called after the atexit handlers now. - The libc executes atexit handlers in the application context, which supports the I/O operations in those handles, in particular the closing of file descriptors. Fixes #3851 --- repos/base/lib/symbols/ld | 6 +- .../base/src/include/base/internal/globals.h | 1 - repos/base/src/lib/cxx/misc.cc | 40 +--- repos/base/src/lib/ldso/main.cc | 37 ++-- repos/base/src/lib/startup/_main.cc | 193 +----------------- .../base/src/lib/startup/init_main_thread.cc | 1 - repos/base/src/test/sanitizer/main.cc | 7 + .../libports/lib/symbols/libsanitizer_common | 1 + repos/libports/ports/sanitizer.hash | 2 +- repos/libports/recipes/pkg/test-ldso/runtime | 4 +- repos/libports/src/lib/gcov/libc/libc.cc | 7 - repos/libports/src/lib/libc/atexit.cc | 74 ++++++- repos/libports/src/lib/libc/exit.cc | 5 + repos/libports/src/lib/libc/internal/atexit.h | 127 ++++++++++++ repos/libports/src/lib/libc/internal/init.h | 6 + repos/libports/src/lib/libc/internal/kernel.h | 3 + repos/libports/src/lib/libc/kernel.cc | 2 + .../src/lib/sanitizer/sanitizer.patch | 34 ++- 18 files changed, 287 insertions(+), 263 deletions(-) create mode 100644 repos/libports/src/lib/libc/internal/atexit.h diff --git a/repos/base/lib/symbols/ld b/repos/base/lib/symbols/ld index 6d73431493..1ee666eaba 100644 --- a/repos/base/lib/symbols/ld +++ b/repos/base/lib/symbols/ld @@ -39,9 +39,7 @@ # _Z11genode_exiti T -_Z13genode_atexitPFvvE T _Z16main_thread_utcbv T -_Z21genode___cxa_finalizePv T _Z22__ldso_raise_exceptionv T _ZN5Timer10Connection16schedule_timeoutEN6Genode12MicrosecondsERNS1_11Time_source15Timeout_handlerE T _ZN5Timer10Connection18_schedule_one_shotERN6Genode7TimeoutENS1_12MicrosecondsE T @@ -625,12 +623,12 @@ _ZTVSt9exception D 40 _ZTVSt9type_info D 64 _ZdlPv W _ZdlPvm W -__aeabi_atexit T +__aeabi_atexit W __aeabi_unwind_cpp_pr0 T __aeabi_unwind_cpp_pr1 T __cxa_allocate_dependent_exception T __cxa_allocate_exception T -__cxa_atexit T +__cxa_atexit W __cxa_bad_cast T __cxa_bad_typeid T __cxa_begin_catch T diff --git a/repos/base/src/include/base/internal/globals.h b/repos/base/src/include/base/internal/globals.h index 4a210fd40c..4eeb3aa8c2 100644 --- a/repos/base/src/include/base/internal/globals.h +++ b/repos/base/src/include/base/internal/globals.h @@ -38,7 +38,6 @@ namespace Genode { void init_root_proxy(Env &); void init_tracing(Env &); void init_log(Parent &); - void init_exit(Parent &); void init_parent_resource_requests(Env &); void init_heartbeat_monitoring(Env &); void deinit_heartbeat_monitoring(); diff --git a/repos/base/src/lib/cxx/misc.cc b/repos/base/src/lib/cxx/misc.cc index ae845d4ce7..7be5c76e05 100644 --- a/repos/base/src/lib/cxx/misc.cc +++ b/repos/base/src/lib/cxx/misc.cc @@ -41,29 +41,16 @@ extern "C" void __pure_virtual() } -/** - * Prototype for exit-handler support function provided by '_main.cc' +/* + * Plain Genode components do not support the atexit mechanism. + * + * To accommodate applications that depend on this mechansim, the libc + * overrides this weak no-op function with a working implementation. */ -extern int genode___cxa_atexit(void(*func)(void*), void *arg, - void *dso_handle); - - -extern "C" int __cxa_atexit(void(*func)(void*), void *arg, - void *dso_handle) +extern "C" __attribute__((weak)) +int __cxa_atexit(void(*)(void*), void *, void *) { - return genode___cxa_atexit(func, arg, dso_handle); -} - - -/** - * Prototype for finalize support function provided by '_main.cc' - */ -extern int genode___cxa_finalize(void *dso); - - -extern "C" void __cxa_finalize(void *dso) -{ - genode___cxa_finalize(dso); + return -1; } @@ -71,11 +58,10 @@ extern "C" void __cxa_finalize(void *dso) ** Support required for ARM EABI ** ***********************************/ - -extern "C" int __aeabi_atexit(void *arg, void(*func)(void*), - void *dso_handle) +extern "C" __attribute__((weak)) +int __aeabi_atexit(void *, void(*)(void*), void *) { - return genode___cxa_atexit(func, arg, dso_handle); + return -1; } @@ -118,10 +104,6 @@ extern "C" void abort(void) Genode::warning("abort called - thread: ", name.string()); - /* Notify the parent of failure */ - if (name != "main") - genode_exit(1); - Genode::sleep_forever(); } diff --git a/repos/base/src/lib/ldso/main.cc b/repos/base/src/lib/ldso/main.cc index 157ccd972c..9ac7c9f307 100644 --- a/repos/base/src/lib/ldso/main.cc +++ b/repos/base/src/lib/ldso/main.cc @@ -19,6 +19,7 @@ #include #include #include +#include /* base-internal includes */ #include @@ -43,15 +44,11 @@ namespace Linker { }; static Binary *binary_ptr = nullptr; +static Parent *parent_ptr = nullptr; bool Linker::verbose = false; Stage Linker::stage = STAGE_BINARY; Link_map *Link_map::first; -/** - * Registers dtors - */ -int genode_atexit(Linker::Func); - Linker::Region_map::Constructible_region_map &Linker::Region_map::r() { @@ -344,8 +341,6 @@ extern char **genode_argv; extern int genode_argc; extern char **genode_envp; -void genode_exit(int status); - static int exit_status; static void exit_on_suspended() { genode_exit(exit_status); } @@ -411,19 +406,22 @@ struct Linker::Binary : private Root_object, public Elf_object { Init::list()->exec_static_constructors(); - /* call static constructors and register destructors */ + /* call static constructors */ Func * const ctors_start = (Func *)lookup_symbol("_ctors_start"); Func * const ctors_end = (Func *)lookup_symbol("_ctors_end"); for (Func * ctor = ctors_end; ctor != ctors_start; (*--ctor)()); - Func * const dtors_start = (Func *)lookup_symbol("_dtors_start"); - Func * const dtors_end = (Func *)lookup_symbol("_dtors_end"); - for (Func * dtor = dtors_start; dtor != dtors_end; genode_atexit(*dtor++)); - static_construction_finished = true; stage = STAGE_SO; } + void call_dtors() + { + Func * const dtors_start = (Func *)lookup_symbol("_dtors_start"); + Func * const dtors_end = (Func *)lookup_symbol("_dtors_end"); + for (Func * dtor = dtors_end; dtor != dtors_start; (*--dtor)()); + } + void call_entry_point(Env &env) { /* apply the component-provided stack size */ @@ -496,6 +494,19 @@ struct Linker::Binary : private Root_object, public Elf_object }; +void genode_exit(int status) +{ + binary_ptr->call_dtors(); + + /* inform parent about the exit status */ + if (parent_ptr) + parent_ptr->exit(status); + + /* wait for destruction by the parent */ + Genode::sleep_forever(); +} + + /********************************** ** Linker object implementation ** **********************************/ @@ -791,6 +802,8 @@ void Component::construct(Genode::Env &env) verbose = config.verbose(); + parent_ptr = &env.parent(); + /* load binary and all dependencies */ try { binary_ptr = unmanaged_singleton(env, *heap(), config, binary_name()); diff --git a/repos/base/src/lib/startup/_main.cc b/repos/base/src/lib/startup/_main.cc index 3c72589913..5d6780a17a 100644 --- a/repos/base/src/lib/startup/_main.cc +++ b/repos/base/src/lib/startup/_main.cc @@ -8,8 +8,6 @@ * The startup code calls constructors for static objects before calling * main(). Furthermore, this file contains the support of exit handlers * and destructors. - * - * Some code within this file is based on 'atexit.c' of FreeBSD's libc. */ /* @@ -29,176 +27,8 @@ #include #include - -enum { ATEXIT_SIZE = 256 }; - - -/*************** - ** C++ stuff ** - ***************/ - void * __dso_handle = 0; -enum Atexit_fn_type { ATEXIT_FN_EMPTY, ATEXIT_FN_STD, ATEXIT_FN_CXA }; - -struct atexit_fn -{ - Atexit_fn_type fn_type; - union - { - void (*std_func)(void); - void (*cxa_func)(void *); - } fn_ptr; /* function pointer */ - void *fn_arg; /* argument for CXA callback */ - void *fn_dso; /* shared module handle */ -}; - -/* all members are initialized with 0 */ -static struct atexit -{ - bool enabled; - int index; - struct atexit_fn fns[ATEXIT_SIZE]; -} _atexit; - - -static Genode::Mutex &atexit_mutex() -{ - static Genode::Mutex _atexit_lock; - return _atexit_lock; -} - - -static void atexit_enable() -{ - _atexit.enabled = true; -} - - -static int atexit_register(struct atexit_fn *fn) -{ - Genode::Mutex::Guard atexit_lock_guard(atexit_mutex()); - - if (!_atexit.enabled) - return 0; - - if (_atexit.index >= ATEXIT_SIZE) { - Genode::error("Cannot register exit handler - ATEXIT_SIZE reached"); - return -1; - } - - _atexit.fns[_atexit.index++] = *fn; - - return 0; -} - - -/** - * Register a function to be performed at exit - */ -int genode_atexit(void (*func)(void)) -{ - struct atexit_fn fn; - int error; - - fn.fn_type = ATEXIT_FN_STD; - fn.fn_ptr.std_func = func; - fn.fn_arg = 0; - fn.fn_dso = 0; - - error = atexit_register(&fn); - return (error); -} - - -/** - * Register a function to be performed at exit or when an shared object - * with given dso handle is unloaded dynamically. - * - * This function is called directly by compiler generated code, so - * it needs to be declared as extern "C" and cannot be local to - * the cxx lib. - */ -int genode___cxa_atexit(void (*func)(void*), void *arg, void *dso) -{ - struct atexit_fn fn; - int error; - - fn.fn_type = ATEXIT_FN_CXA; - fn.fn_ptr.cxa_func = func; - fn.fn_arg = arg; - fn.fn_dso = dso; - - error = atexit_register(&fn); - return (error); -} - - -/* - * Call all handlers registered with __cxa_atexit for the shared - * object owning 'dso'. Note: if 'dso' is NULL, then all remaining - * handlers are called. - */ -void genode___cxa_finalize(void *dso) -{ - struct atexit_fn fn; - int n = 0; - - atexit_mutex().acquire(); - for (n = _atexit.index; --n >= 0;) { - if (_atexit.fns[n].fn_type == ATEXIT_FN_EMPTY) - continue; /* already been called */ - if (dso != 0 && dso != _atexit.fns[n].fn_dso) - continue; /* wrong DSO */ - fn = _atexit.fns[n]; - - /* - * Mark entry to indicate that this particular handler - * has already been called. - */ - _atexit.fns[n].fn_type = ATEXIT_FN_EMPTY; - atexit_mutex().release(); - - /* call the function of correct type */ - if (fn.fn_type == ATEXIT_FN_CXA) - fn.fn_ptr.cxa_func(fn.fn_arg); - else if (fn.fn_type == ATEXIT_FN_STD) - fn.fn_ptr.std_func(); - - atexit_mutex().acquire(); - } - atexit_mutex().release(); -} - - -extern "C" void __cxa_finalize(void *dso); - -static Genode::Parent *_parent_ptr; - - -namespace Genode { void init_exit(Parent &parent) { _parent_ptr = &parent; } } - - -/** - * Terminate the process. - */ -void genode_exit(int status) -{ - /* call handlers registered with 'atexit()' or '__cxa_atexit()' */ - __cxa_finalize(0); - - /* call destructors for global static objects. */ - void (**func)(); - for (func = &_dtors_start; func != &_dtors_end; (*func++)()); - - /* inform parent about the exit status */ - if (_parent_ptr) - _parent_ptr->exit(status); - - /* wait for destruction by the parent */ - Genode::sleep_forever(); -} - /** * Dummy default arguments for main function @@ -242,16 +72,6 @@ namespace Genode { extern "C" int _main() { - /* - * Allow exit handlers to be registered. - * - * This is done after the creation of the environment to prevent its - * destruction. The environment is still needed to notify the parent - * after all exit handlers (including static object destructors) have - * been called. - */ - atexit_enable(); - Genode::bootstrap_component(); /* never reached */ @@ -259,22 +79,13 @@ extern "C" int _main() } -static int exit_status; -static void exit_on_suspended() { genode_exit(exit_status); } - - extern int main(int argc, char **argv, char **envp); void Component::construct(Genode::Env &env) __attribute__((weak)); -void Component::construct(Genode::Env &env) +void Component::construct(Genode::Env &) { /* call real main function */ - exit_status = main(genode_argc, genode_argv, genode_envp); - - /* trigger suspend in the entry point */ - env.ep().schedule_suspend(exit_on_suspended, nullptr); - - /* return to entrypoint and exit via exit_on_suspended() */ + main(genode_argc, genode_argv, genode_envp); } diff --git a/repos/base/src/lib/startup/init_main_thread.cc b/repos/base/src/lib/startup/init_main_thread.cc index 771ae7c6ca..e0a6efc392 100644 --- a/repos/base/src/lib/startup/init_main_thread.cc +++ b/repos/base/src/lib/startup/init_main_thread.cc @@ -106,7 +106,6 @@ extern "C" void init_main_thread() */ (void*)env_deprecated(); init_log(*env_deprecated()->parent()); - init_exit(*env_deprecated()->parent()); /* create a thread object for the main thread */ main_thread(); diff --git a/repos/base/src/test/sanitizer/main.cc b/repos/base/src/test/sanitizer/main.cc index 2c723d287c..9f1fcb444a 100644 --- a/repos/base/src/test/sanitizer/main.cc +++ b/repos/base/src/test/sanitizer/main.cc @@ -15,6 +15,7 @@ #include extern void sanitizer_init(Genode::Env &); +extern void sanitizer_exit(); void Component::construct(Genode::Env &env) { @@ -30,4 +31,10 @@ void Component::construct(Genode::Env &env) int * volatile ptr = nullptr; *ptr = 0x55; + + /* + * Not reached in this test, but calls exit handlers registered by + * sanitizers in general. + */ + sanitizer_exit(); } diff --git a/repos/libports/lib/symbols/libsanitizer_common b/repos/libports/lib/symbols/libsanitizer_common index 5047a42161..9b591f1e11 100644 --- a/repos/libports/lib/symbols/libsanitizer_common +++ b/repos/libports/lib/symbols/libsanitizer_common @@ -1,4 +1,5 @@ OnPrint W +_Z14sanitizer_exitv T _Z14sanitizer_initRN6Genode3EnvE T _ZN11__sanitizer10ExtractIntEPKcS1_Pi T _ZN11__sanitizer10FlagParser10ll_strndupEPKcm T diff --git a/repos/libports/ports/sanitizer.hash b/repos/libports/ports/sanitizer.hash index 76d672cd24..af638a244e 100644 --- a/repos/libports/ports/sanitizer.hash +++ b/repos/libports/ports/sanitizer.hash @@ -1 +1 @@ -181889c6d4af01eed6f89b2df496b83896d18034 +3ac05b0fdf5b49cd1b375afe08095c4c1a6c5289 diff --git a/repos/libports/recipes/pkg/test-ldso/runtime b/repos/libports/recipes/pkg/test-ldso/runtime index 0530aae605..389c748665 100644 --- a/repos/libports/recipes/pkg/test-ldso/runtime +++ b/repos/libports/recipes/pkg/test-ldso/runtime @@ -94,13 +94,13 @@ [init -> test-ldso] ~Lib_1_local_3 0x12345675* [init -> test-ldso] ~Local_2 0x1020303d* [init -> test-ldso] ~Local_1 0x5060707d* - [init -> test-ldso] attr_destructor_2 0x4030200d* - [init -> test-ldso] attr_destructor_1 0x8070604c* [init -> test-ldso] ~Global_2 0x1020301* [init -> test-ldso] ~Global_1 0x5060705* [init -> test-ldso] ~Lib_1_global_2 0x1020301* [init -> test-ldso] ~Lib_1_global_1 0x5060705* [init -> test-ldso] ~Lib_2_global 0x11223340* + [init -> test-ldso] attr_destructor_2 0x4030200d* + [init -> test-ldso] attr_destructor_1 0x8070604c* [init] child "test-ldso" exited with exit value 123 diff --git a/repos/libports/src/lib/gcov/libc/libc.cc b/repos/libports/src/lib/gcov/libc/libc.cc index 9a45b30cb2..3bd82b49b2 100644 --- a/repos/libports/src/lib/gcov/libc/libc.cc +++ b/repos/libports/src/lib/gcov/libc/libc.cc @@ -68,13 +68,6 @@ extern "C" void abort() } -extern void genode_atexit(void (*func)(void)); -extern "C" void atexit(void (*func)(void)) -{ - genode_atexit(func); -} - - extern "C" int atoi(const char *nptr) { Genode::error("atoi() called: not implemented"); diff --git a/repos/libports/src/lib/libc/atexit.cc b/repos/libports/src/lib/libc/atexit.cc index 4e1e62c635..4300db0621 100644 --- a/repos/libports/src/lib/libc/atexit.cc +++ b/repos/libports/src/lib/libc/atexit.cc @@ -11,14 +11,78 @@ * under the terms of the GNU Affero General Public License version 3. */ -extern void genode_atexit(void (*func)(void)); -extern "C" void atexit(void (*func)(void)) +/* Genode includes */ +#include + +/* libc includes */ +#include + +/* libc-internal includes */ +#include + +using namespace Libc; + + +static Libc::Atexit *_atexit_ptr; + + +void Libc::init_atexit(Atexit &atexit) { - genode_atexit(func); + _atexit_ptr = &atexit; } -extern void genode___cxa_finalize(void *dso); + +void Libc::execute_atexit_handlers_in_application_context() +{ + if (!_atexit_ptr) { + error("missing call of 'init_atexit'"); + sleep_forever(); + } + + /* + * The atexit handlers must be executed in application context because the + * handlers may perform I/O such as the closing of file descriptors. + */ + with_libc([&] () { + _atexit_ptr->execute_handlers(nullptr); + }); +} + + +/********************* + ** CXA ABI support ** + *********************/ + +/* + * The C++ compiler generates calls to '__cxa_atexit' for each object that + * is instantiated as static local variable. + */ + +extern "C" int __cxa_atexit(void (*func)(void*), void *arg, void *dso) +{ + if (!_atexit_ptr) + return -1; + + _atexit_ptr->register_cxa_handler(func, arg, dso); + return 0; +} + + +extern "C" int __aeabi_atexit(void *arg, void(*func)(void*), void *dso) +{ + return __cxa_atexit(func, arg, dso); +} + + extern "C" void __cxa_finalize(void *dso) { - genode___cxa_finalize(dso); + execute_atexit_handlers_in_application_context(); } + + +extern "C" int atexit(void (*func)(void)) +{ + _atexit_ptr->register_std_handler(func); + return 0; +} + diff --git a/repos/libports/src/lib/libc/exit.cc b/repos/libports/src/lib/libc/exit.cc index bf178584f0..fb321e7dc6 100644 --- a/repos/libports/src/lib/libc/exit.cc +++ b/repos/libports/src/lib/libc/exit.cc @@ -16,11 +16,16 @@ /* libc-internal includes */ #include +#include + extern void genode_exit(int status) __attribute__((noreturn)); + extern "C" void _exit(int status) { + Libc::execute_atexit_handlers_in_application_context(); + genode_exit(status); } diff --git a/repos/libports/src/lib/libc/internal/atexit.h b/repos/libports/src/lib/libc/internal/atexit.h new file mode 100644 index 0000000000..b25a9d5474 --- /dev/null +++ b/repos/libports/src/lib/libc/internal/atexit.h @@ -0,0 +1,127 @@ +/* + * \brief POSIX atexit handling + * \author Norman Feske + * \date 2020-08-17 + */ + +/* + * Copyright (C) 2020 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU Affero General Public License version 3. + */ + +#ifndef _LIBC__INTERNAL__ATEXIT_H_ +#define _LIBC__INTERNAL__ATEXIT_H_ + +/* Genode includes */ +#include +#include +#include + +/* libc-internal includes */ +#include +#include + +namespace Libc { struct Atexit; } + + +struct Libc::Atexit : Noncopyable +{ + private: + + using Allocator = Genode::Allocator; + + Allocator &_alloc; + + struct Handler : List::Element + { + enum class Type { STD, CXA }; + + Type type; + + void (*std_func)(void); + void (*cxa_func)(void *); + + void *fn_arg; /* argument for CXA callback */ + void *dso; /* shared object handle */ + + void execute() + { + switch (type) { + case Type::CXA: cxa_func(fn_arg); break; + case Type::STD: std_func(); break; + } + } + }; + + Mutex _mutex { }; + + List _handlers { }; + + public: + + Atexit(Allocator &alloc) : _alloc(alloc) { } + + void register_cxa_handler(void (*func)(void*), void *arg, void *dso) + { + Mutex::Guard guard(_mutex); + + _handlers.insert( + new (_alloc) Handler { .type = Handler::Type::CXA, + .std_func = nullptr, + .cxa_func = func, + .fn_arg = arg, + .dso = dso }); + } + + void register_std_handler(void (*func)()) + { + Mutex::Guard guard(_mutex); + + _handlers.insert( + new (_alloc) Handler { .type = Handler::Type::STD, + .std_func = func, + .cxa_func = nullptr, + .fn_arg = nullptr, + .dso = nullptr }); + } + + /* + * Execute all exit handler for shared object 'dso'. + * + * If 'dso' is nullptr, all remaining handlers are executed. + */ + void execute_handlers(void *dso) + { + auto try_execute_one_matching_handler = [&] () + { + Handler *handler_ptr = nullptr; + + /* search matching handler */ + { + Mutex::Guard guard(_mutex); + + handler_ptr = _handlers.first(); + while (handler_ptr && dso && (handler_ptr->dso != dso)) { + handler_ptr = handler_ptr->next(); + } + } + + if (!handler_ptr) + return false; + + handler_ptr->execute(); + _handlers.remove(handler_ptr); + destroy(_alloc, handler_ptr); + return true; + }; + + while (try_execute_one_matching_handler()); + } +}; + + +namespace Libc { void execute_atexit_handlers_in_application_context(); } + +#endif /* _LIBC__INTERNAL__ATEXIT_H_ */ diff --git a/repos/libports/src/lib/libc/internal/init.h b/repos/libports/src/lib/libc/internal/init.h index da20ad703b..a75bd65222 100644 --- a/repos/libports/src/lib/libc/internal/init.h +++ b/repos/libports/src/lib/libc/internal/init.h @@ -40,6 +40,7 @@ namespace Libc { struct File_descriptor_allocator; struct Timer_accessor; struct Cwd; + struct Atexit; /** * Support for shared libraries @@ -143,6 +144,11 @@ namespace Libc { * Signal handling */ void init_signal(Signal &); + + /** + * Atexit handling + */ + void init_atexit(Atexit &); } #endif /* _LIBC__INTERNAL__INIT_H_ */ diff --git a/repos/libports/src/lib/libc/internal/kernel.h b/repos/libports/src/lib/libc/internal/kernel.h index b531ae25fc..e829117b08 100644 --- a/repos/libports/src/lib/libc/internal/kernel.h +++ b/repos/libports/src/lib/libc/internal/kernel.h @@ -42,6 +42,7 @@ #include #include #include +#include namespace Libc { class Kernel; @@ -192,6 +193,8 @@ struct Libc::Kernel final : Vfs::Io_response_handler, Signal _signal { _pid }; + Atexit _atexit { _heap }; + Reconstructible> _resume_main_handler { _env.ep(), *this, &Kernel::_resume_main }; diff --git a/repos/libports/src/lib/libc/kernel.cc b/repos/libports/src/lib/libc/kernel.cc index af4ba55b18..f20c1f0f1b 100644 --- a/repos/libports/src/lib/libc/kernel.cc +++ b/repos/libports/src/lib/libc/kernel.cc @@ -510,6 +510,8 @@ Libc::Kernel::Kernel(Genode::Env &env, Genode::Allocator &heap) : _env(env), _heap(heap) { + init_atexit(_atexit); + atexit(close_file_descriptors_on_exit); init_semaphore_support(_timer_accessor); diff --git a/repos/libports/src/lib/sanitizer/sanitizer.patch b/repos/libports/src/lib/sanitizer/sanitizer.patch index db78a5e2e6..30ea08c3e3 100644 --- a/repos/libports/src/lib/sanitizer/sanitizer.patch +++ b/repos/libports/src/lib/sanitizer/sanitizer.patch @@ -4,7 +4,7 @@ From: Christian Prochaska --- - sanitizer_common/sanitizer_genode.cc | 330 ++++++++++++++++++++ + sanitizer_common/sanitizer_genode.cc | 345 ++++++++++++++++++++ sanitizer_common/sanitizer_internal_defs.h | 6 sanitizer_common/sanitizer_platform.h | 4 sanitizer_common/sanitizer_posix.h | 2 @@ -13,15 +13,15 @@ From: Christian Prochaska sanitizer_common/sanitizer_symbolizer_libcdep.cc | 10 - .../sanitizer_symbolizer_posix_libcdep.cc | 31 +- ubsan/ubsan_diag.cc | 4 - 9 files changed, 376 insertions(+), 15 deletions(-) + 9 files changed, 391 insertions(+), 15 deletions(-) create mode 100644 sanitizer_common/sanitizer_genode.cc diff --git a/sanitizer_common/sanitizer_genode.cc b/sanitizer_common/sanitizer_genode.cc new file mode 100644 -index 0000000..cd2bc92 +index 0000000..52dda98 --- /dev/null +++ b/sanitizer_common/sanitizer_genode.cc -@@ -0,0 +1,330 @@ +@@ -0,0 +1,345 @@ +/* + * \brief Genode-specific functions from sanitizer_common.h + * and sanitizer_libc.h @@ -48,7 +48,6 @@ index 0000000..cd2bc92 +using namespace __sanitizer; + + -+extern int genode_atexit(void (*func)(void)); +extern void genode_exit(int) __attribute__((noreturn)); + + @@ -74,11 +73,20 @@ index 0000000..cd2bc92 + +void sanitizer_init(Genode::Env &env) +{ -+Genode::log("sanitizer_init()"); + genode_env = &env; +} + + ++static void (*atexit_func)(void) = nullptr; ++ ++ ++void sanitizer_exit() ++{ ++ if (atexit_func) ++ atexit_func(); ++} ++ ++ +/* sanitizer_common.h */ + + @@ -91,7 +99,14 @@ index 0000000..cd2bc92 + +int __sanitizer::Atexit(void (*function)(void)) +{ -+ return genode_atexit(function); ++ if (atexit_func) { ++ Genode::error("sanitizer: ", __func__, ++ ": only one exit handler is currently supported"); ++ return -1; ++ } ++ ++ atexit_func = function; ++ return 0; +} + + @@ -629,14 +644,13 @@ index 978d966..7d38a9b 100644 using namespace __ubsan; -@@ -209,8 +211,10 @@ static void RenderText(InternalScopedString *Buffer, const char *Message, +@@ -209,7 +211,9 @@ static void RenderText(InternalScopedString *Buffer, const char *Message, #if SANITIZER_WINDOWS sprintf_s(FloatBuffer, sizeof(FloatBuffer), "%Lg", (long double)A.Float); #else +#if 0 snprintf(FloatBuffer, sizeof(FloatBuffer), "%Lg", (long double)A.Float); - #endif +#endif + #endif Buffer->append("%s", FloatBuffer); break; - }