From 8d9dd0df459db5b8850c51a9f1d9011bb1cd5f3d Mon Sep 17 00:00:00 2001
From: 4lDO2 <4lDO2@protonmail.com>
Date: Thu, 27 Apr 2023 13:23:59 +0200
Subject: [PATCH] Improve pthread_cleanup_{push,pop}.

---
 src/header/bits_pthread/cbindgen.toml | 21 ++++++++++-----------
 src/header/pthread/mod.rs             |  2 ++
 src/pthread/mod.rs                    | 10 +++++-----
 3 files changed, 17 insertions(+), 16 deletions(-)

diff --git a/src/header/bits_pthread/cbindgen.toml b/src/header/bits_pthread/cbindgen.toml
index cea35466..34956c00 100644
--- a/src/header/bits_pthread/cbindgen.toml
+++ b/src/header/bits_pthread/cbindgen.toml
@@ -4,6 +4,7 @@ language = "C"
 style = "type"
 no_includes = true
 cpp_compat = true
+# TODO: Any better way to implement pthread_cleanup_push/pthread_cleanup_pop?
 after_includes = """
 #define PTHREAD_COND_INITIALIZER ((pthread_cond_t){0})
 #define PTHREAD_MUTEX_INITIALIZER ((pthread_mutex_t){0})
@@ -11,17 +12,15 @@ after_includes = """
 #define PTHREAD_RWLOCK_INITIALIZER ((pthread_rwlock_t){0})
 
 #define pthread_cleanup_push(routine, arg) do { \
-  do { \
-    struct { \
-      void (*routine)(void *); \
-      void *arg; \
-      void *prev; \
-    } __relibc_internal_pthread_ll_entry = { \
-      .routine = (routine), \
-      .arg = (arg), \
-    }; \
-    __relibc_internal_pthread_cleanup_push(&__relibc_internal_pthread_ll_entry); \
-  } while(0)
+  struct { \
+    void (*routine)(void *); \
+    void *arg; \
+    void *prev; \
+  } __relibc_internal_pthread_ll_entry = { \
+    .routine = (routine), \
+    .arg = (arg), \
+  }; \
+  __relibc_internal_pthread_cleanup_push(&__relibc_internal_pthread_ll_entry);
 
 #define pthread_cleanup_pop(execute) \
   __relibc_internal_pthread_cleanup_pop((execute)); \
diff --git a/src/header/pthread/mod.rs b/src/header/pthread/mod.rs
index 81e026ef..afad09fd 100644
--- a/src/header/pthread/mod.rs
+++ b/src/header/pthread/mod.rs
@@ -222,6 +222,8 @@ pub(crate) struct CleanupLinkedListEntry {
 #[thread_local]
 pub(crate) static CLEANUP_LL_HEAD: Cell<*const CleanupLinkedListEntry> = Cell::new(core::ptr::null());
 
+// TODO: unwind? setjmp/longjmp?
+
 #[no_mangle]
 pub unsafe extern "C" fn __relibc_internal_pthread_cleanup_push(new_entry: *mut c_void) {
     let new_entry = &mut *new_entry.cast::<CleanupLinkedListEntry>();
diff --git a/src/pthread/mod.rs b/src/pthread/mod.rs
index 1d09c62e..a8766db8 100644
--- a/src/pthread/mod.rs
+++ b/src/pthread/mod.rs
@@ -265,6 +265,11 @@ pub unsafe fn testcancel() {
 }
 
 pub unsafe fn exit_current_thread(retval: Retval) -> ! {
+    // Run pthread_cleanup_push/pthread_cleanup_pop destructors.
+    header::run_destructor_stack();
+
+    header::tls::run_all_destructors();
+
     let this = current_thread().expect("failed to obtain current thread when exiting");
 
     if this.flags.load(Ordering::Acquire) & PthreadFlags::DETACHED.bits() != 0 {
@@ -295,11 +300,6 @@ unsafe extern "C" fn cancel_sighandler(_: c_int) {
     cancel_current_thread();
 }
 unsafe fn cancel_current_thread() {
-    // Run pthread_cleanup_push/pthread_cleanup_pop destructors.
-    header::run_destructor_stack();
-
-    header::tls::run_all_destructors();
-
     // Terminate the thread
     exit_current_thread(Retval(header::PTHREAD_CANCELED));
 }
-- 
GitLab