hare

[hare] The Hare programming language
git clone https://git.torresjrjr.com/hare.git
Log | Files | Refs | README | LICENSE

commit f48bb4f864e5dd33cc0a919f5e769b32ed86f159
parent 751e8c0736baee81872a5a29b5f1f832d02e081a
Author: Conrad Hoffmann <ch@bitfehler.net>
Date:   Fri, 26 Aug 2022 14:56:25 +0200

os: run finalization functions on exit()

Currently, when calling os::exit(), no @fini finalization functions are
being run. This commit pulls the initialization and finalization out of
rt::start_ha() and calls the finalization in os::exit() before calling
rt::exit().

Signed-off-by: Conrad Hoffmann <ch@bitfehler.net>

Diffstat:
Mos/+freebsd/exit.ha | 5++++-
Mos/+linux/exit.ha | 5++++-
Mrt/start+libc.ha | 16+++++++++++++++-
Mrt/start+test+libc.ha | 11+++++++++++
Mrt/start+test.ha | 13++++++++++---
Mrt/start.ha | 13++++++++++---
6 files changed, 54 insertions(+), 9 deletions(-)

diff --git a/os/+freebsd/exit.ha b/os/+freebsd/exit.ha @@ -3,4 +3,7 @@ use rt; // Exit the program with the provided status code. -export @noreturn fn exit(status: int) void = rt::exit(status); +export @noreturn fn exit(status: int) void = { + rt::fini(); + rt::exit(status); +}; diff --git a/os/+linux/exit.ha b/os/+linux/exit.ha @@ -3,4 +3,7 @@ use rt; // Exit the program with the provided status code. -export @noreturn fn exit(status: int) void = rt::exit(status); +export @noreturn fn exit(status: int) void = { + rt::fini(); + rt::exit(status); +}; diff --git a/rt/start+libc.ha b/rt/start+libc.ha @@ -4,8 +4,22 @@ @symbol("main") fn main() void; @symbol("exit") fn c_exit(status: int) void; +const @symbol("__fini_array_start") fini_start: [*]*fn() void; +const @symbol("__fini_array_end") fini_end: [*]*fn() void; + +export fn init() void = void; + +// Run all global finalization functions. +export fn fini() void = { + const nfini = (&fini_end: uintptr - &fini_start: uintptr): size + / size(*fn() void); + for (let i = 0z; i < nfini; i += 1) { + fini_start[i](); + }; +}; + export @noreturn fn start_ha() void = { - // libc runs @init and @fini for us + // libc runs @init and @fini for us (unless rt::exit() is called) main(); c_exit(0); }; diff --git a/rt/start+test+libc.ha b/rt/start+test+libc.ha @@ -1,6 +1,17 @@ // License: MPL-2.0 // (c) 2021 Alexey Yerin <yyp@disroot.org> +export fn init() void = void; + +// Run all global finalization functions. +export fn fini() void = { + const nfini = (&fini_end: uintptr - &fini_start: uintptr): size + / size(*fn() void); + for (let i = 0z; i < nfini; i += 1) { + fini_start[i](); + }; +}; + export @symbol("main") fn main() int = { const nfail = tests_main(); return if (nfail > 0) 1 else 0; diff --git a/rt/start+test.ha b/rt/start+test.ha @@ -6,20 +6,27 @@ const @symbol("__init_array_end") init_end: [*]*fn() void; const @symbol("__fini_array_start") fini_start: [*]*fn() void; const @symbol("__fini_array_end") fini_end: [*]*fn() void; -export @noreturn fn start_ha() void = { +// Run all global initialization functions. +export fn init() void = { const ninit = (&init_end: uintptr - &init_start: uintptr): size / size(*fn() void); for (let i = 0z; i < ninit; i += 1) { init_start[i](); }; +}; - let nfail = tests_main(); - +// Run all global finalization functions. +export fn fini() void = { const nfini = (&fini_end: uintptr - &fini_start: uintptr): size / size(*fn() void); for (let i = 0z; i < nfini; i += 1) { fini_start[i](); }; +}; +export @noreturn fn start_ha() void = { + init(); + let nfail = tests_main(); + fini(); exit(if (nfail > 0) 1 else 0); }; diff --git a/rt/start.ha b/rt/start.ha @@ -9,20 +9,27 @@ const @symbol("__init_array_end") init_end: [*]*fn() void; const @symbol("__fini_array_start") fini_start: [*]*fn() void; const @symbol("__fini_array_end") fini_end: [*]*fn() void; -export @noreturn fn start_ha() void = { +// Run all global initialization functions. +export fn init() void = { const ninit = (&init_end: uintptr - &init_start: uintptr): size / size(*fn() void); for (let i = 0z; i < ninit; i += 1) { init_start[i](); }; +}; - main(); - +// Run all global finalization functions. +export fn fini() void = { const nfini = (&fini_end: uintptr - &fini_start: uintptr): size / size(*fn() void); for (let i = 0z; i < nfini; i += 1) { fini_start[i](); }; +}; +export @noreturn fn start_ha() void = { + init(); + main(); + fini(); exit(0); };