From 633282872557afa51f9bbaeef1b187f9e16faa97 Mon Sep 17 00:00:00 2001
From: Mateusz Tabaka <tab.debugteam@gmail.com>
Date: Tue, 29 Dec 2020 17:27:09 +0100
Subject: [PATCH] Call DSO destructors during exit()

---
 src/header/stdlib/mod.rs | 3 +++
 src/ld_so/linker.rs      | 6 ++++++
 src/ld_so/mod.rs         | 9 +++++++++
 src/ld_so/src/lib.rs     | 1 -
 tests/Makefile           | 8 +-------
 5 files changed, 19 insertions(+), 8 deletions(-)

diff --git a/src/header/stdlib/mod.rs b/src/header/stdlib/mod.rs
index c5fd5d1be..daaf72bea 100644
--- a/src/header/stdlib/mod.rs
+++ b/src/header/stdlib/mod.rs
@@ -21,6 +21,7 @@ use crate::{
         unistd::{self, sysconf, _SC_PAGESIZE},
         wchar::*,
     },
+    ld_so,
     platform::{self, types::*, Pal, Sys},
 };
 
@@ -292,6 +293,8 @@ pub unsafe extern "C" fn exit(status: c_int) {
 
     _fini();
 
+    ld_so::fini();
+
     pthread_terminate();
 
     Sys::exit(status);
diff --git a/src/ld_so/linker.rs b/src/ld_so/linker.rs
index 21d35b180..67bd46747 100644
--- a/src/ld_so/linker.rs
+++ b/src/ld_so/linker.rs
@@ -113,6 +113,12 @@ impl Linker {
         }
     }
 
+    pub fn fini(&self) {
+        for obj in self.objects.values() {
+            obj.run_fini();
+        }
+    }
+
     fn load_object(
         &mut self,
         path: &str,
diff --git a/src/ld_so/mod.rs b/src/ld_so/mod.rs
index 7a1324387..e4e62282b 100644
--- a/src/ld_so/mod.rs
+++ b/src/ld_so/mod.rs
@@ -108,3 +108,12 @@ pub unsafe fn init(sp: &'static Stack) {
 
 #[cfg(target_os = "redox")]
 pub unsafe fn init(_sp: &'static Stack) {}
+
+pub unsafe fn fini() {
+    if let Some(tcb) = Tcb::current() {
+        if tcb.linker_ptr != ptr::null_mut() {
+            let linker = (&*tcb.linker_ptr).lock();
+            linker.fini();
+        }
+    }
+}
diff --git a/src/ld_so/src/lib.rs b/src/ld_so/src/lib.rs
index 69248ec88..d29baa44a 100644
--- a/src/ld_so/src/lib.rs
+++ b/src/ld_so/src/lib.rs
@@ -34,7 +34,6 @@ next:   pop rsi
         xor r11, r11
         fninit
         jmp rax
-        # TODO: Loader::fini() should be called about here
         "
         :
         :
diff --git a/tests/Makefile b/tests/Makefile
index 240d88188..cb482cd3f 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -6,6 +6,7 @@ EXPECT_NAMES=\
 	assert \
 	constructor \
 	ctype \
+	destructor \
 	dirent/scandir \
 	errno \
 	error \
@@ -119,11 +120,6 @@ EXPECT_NAMES=\
 	# mkfifo
 	# netdb/netdb \
 
-# need to call fini in ld_so's _start
-STATIC_ONLY_NAMES=\
-	destructor
-
-
 DYNAMIC_ONLY_NAMES=\
 	dlfcn
 
@@ -155,11 +151,9 @@ NAMES=\
 #	time/times
 
 BINS=$(patsubst %,bins_static/%,$(NAMES))
-BINS+=$(patsubst %,bins_static/%,$(STATIC_ONLY_NAMES))
 BINS+=$(patsubst %,bins_dynamic/%,$(NAMES))
 BINS+=$(patsubst %,bins_dynamic/%,$(DYNAMIC_ONLY_NAMES))
 EXPECT_BINS=$(patsubst %,bins_static/%,$(EXPECT_NAMES))
-EXPECT_BINS+=$(patsubst %,bins_static/%,$(STATIC_ONLY_NAMES))
 EXPECT_BINS+=$(patsubst %,bins_dynamic/%,$(EXPECT_NAMES))
 EXPECT_BINS+=$(patsubst %,bins_dynamic/%,$(DYNAMIC_ONLY_NAMES))
 
-- 
GitLab