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:
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);
};