While mingw-w64 might have been deemed to enable projects, which typically build with the Microsoft compiler and linker, to build with the GNU compiler and linker with little modification, sometimes I do think we have payed too much in mimicking some non-standard, weird, or even broken behaviors [1] [2]. If, for some necessary reasons, we can't fix them, it might be possible to build up a new series of APIs according to the C, POSIX, and Itanium ABI [3] standards.

mcfgthread [4] has been designed to conform to these standards, in startup and termination behavior, by providing these functions:

   ```
   void __MCF_exit(int status);  // for `exit` (C89)
   void __MCF_quick_exit(int status);  // for `quick_exit` (C99)
   void __MCF_Exit(int status);  // for `_Exit` (C99) and `_exit` (POSIX)
   void __MCF_cxa_finalize(void* dso);  // for `__cxa_finalize` (Itanium ABI)

   int __MCF_atexit(__MCF_atexit_callback atfn);  // for `atexit` (C89)
   int __MCF_at_quick_exit(__MCF_atexit_callback atfn);  // for 
`at_quick_exit()` (C99)

   int __MCF_cxa_atexit(__MCF_cxa_dtor_union dtor, void* this,
        void* dso);  // for `__cxa_atexit` (Itanium ABI)
   int __MCF_cxa_at_quick_exit(__MCF_cxa_dtor_union dtor, void* this,
        void* dso);  // for `__cxa_at_quick_exit` (GNU extension)

   int __MCF_thread_atexit(__MCF_atexit_callback atfn);  // extension
   int __MCF_cxa_thread_atexit(__MCF_cxa_dtor_union dtor, void* this,
        void* dso);  // for `__cxa_thread_atexit` (GNU extension)

   int __MCF_cxa_guard_acquire(int64_t* guard);  // for `__cxa_guard_acquire` 
(Itanium ABI)
   void __MCF_cxa_guard_release(int64_t* guard);  // for `__cxa_guard_release` 
(Itanium ABI)
   void __MCF_cxa_guard_abort(int64_t* guard);  // for `__cxa_guard_abort` 
(Itanium ABI)
   ```


To be clear about the responsibilities of the C and C++ runtime libraries, we 
take Linux as an example:

   * `exit()`, `quick_exit()`, `_Exit()` and `__cxa_finalize()` are provided
     by libc.

   * `atexit()` and `at_quick_exit()` are linked statically, as wrappers for
     `__cxa_atexit()` and `__cxa_at_quick_exit()`, respectively; the latter are
     provided by libc.

   * `__cxa_thread_atexit()` is provided by libstdc++, as a wrapper for
     `__cxa_thread_atexit_impl()` [5]; the latter is provided by libc.

   * `__cxa_guard_*()` are provided by libstdc++.


Basing on these facts which we may take as a reference, in order to get standard behaviors, I think it should be acceptable to provide those functions, which are marked as 'provided by libc', in mingw-w64 CRT, as static wrappers to those from mcfgthread.

`__cxa_atexit()` and `__cxa_at_quick_exit()` should be provided by the C runtime. If we can't provide them in a DLL (apparently), we may continue to provide them as static ones. This way, the `dso` argument should always reference the DSO handle of the linking module.


There are still some issues left unsolved, however:

   * The Itanium ABI specifies that, when the main program calls `exit()`, the
     program shall behave like `__cxa_finalize(NULL)` is called; when a shared
     library is unloaded, `__cxa_finalize(dso_handle)` shall be called. This
     requires overriding the `exit()` function from MSVCRT, as well as
     `quick_exit()` from UCRT.

   * The Microsoft documentation says that `_cexit()` would flush all open
     streams. But I fail to observe such behavior; an explicit call to
     `fflush(NULL)` is essential. In the EXE startup code, we must register it
     with `__cxa_atexit(fflush, NULL, NULL)` before any user code is executed.
     Then the call to `_cexit()` seems unnecessary.


Attached are draft patches for the above, sent for comments only.


[1] https://sourceforge.net/p/mingw-w64/mailman/message/37268447/
[2] https://reviews.llvm.org/D102944
[3] https://itanium-cxx-abi.github.io/cxx-abi/abi.html

[4] https://github.com/lhmouse/mcfgthread
[5] https://github.com/gcc-mirror/gcc/blob/2eff4fe383a59de94267352e25f77b29d8e6bb42/libstdc%2B%2B-v3/libsupc%2B%2B/atexit_thread.cc#L51


--
Best regards,
LIU Hao



From 8efa2a31b22f8ed37a31a4f0acbfa943fa8d65e2 Mon Sep 17 00:00:00 2001
From: LIU Hao <[email protected]>
Date: Fri, 7 Oct 2022 22:42:04 +0800
Subject: [PATCH 1/3] crt: Mark `atexit()` as DATA because it's always
 overridden

Signed-off-by: LIU Hao <[email protected]>
---
 mingw-w64-crt/lib-common/msvcr120_app.def.in | 2 +-
 mingw-w64-crt/lib32/msvcr120.def.in          | 2 +-
 mingw-w64-crt/lib32/msvcr120d.def.in         | 2 +-
 mingw-w64-crt/lib32/msvcr70.def              | 2 +-
 mingw-w64-crt/lib32/msvcr71.def              | 2 +-
 mingw-w64-crt/lib32/msvcrt10.def             | 2 +-
 mingw-w64-crt/lib32/msvcrt20.def             | 2 +-
 mingw-w64-crt/lib32/msvcrt40.def             | 2 +-
 mingw-w64-crt/lib64/msvcr120.def.in          | 2 +-
 mingw-w64-crt/lib64/msvcr120d.def.in         | 2 +-
 mingw-w64-crt/libarm32/kernelbase.def        | 2 +-
 mingw-w64-crt/libarm32/msvcr110.def          | 2 +-
 mingw-w64-crt/libarm32/msvcr120_clr0400.def  | 2 +-
 13 files changed, 13 insertions(+), 13 deletions(-)

diff --git a/mingw-w64-crt/lib-common/msvcr120_app.def.in 
b/mingw-w64-crt/lib-common/msvcr120_app.def.in
index 10cf84d07..ddb407d00 100644
--- a/mingw-w64-crt/lib-common/msvcr120_app.def.in
+++ b/mingw-w64-crt/lib-common/msvcr120_app.def.in
@@ -2029,7 +2029,7 @@ F_NON_I386(atanf)
 F_X86_ANY(atanh)
 F_X86_ANY(atanhf)
 F_X86_ANY(atanhl)
-atexit
+atexit DATA
 atof
 atoi
 atol
diff --git a/mingw-w64-crt/lib32/msvcr120.def.in 
b/mingw-w64-crt/lib32/msvcr120.def.in
index 98567a956..82adab07b 100644
--- a/mingw-w64-crt/lib32/msvcr120.def.in
+++ b/mingw-w64-crt/lib32/msvcr120.def.in
@@ -1861,7 +1861,7 @@ atan2
 atanh
 atanhf
 atanhl
-atexit
+atexit DATA
 atof
 atoi
 atol
diff --git a/mingw-w64-crt/lib32/msvcr120d.def.in 
b/mingw-w64-crt/lib32/msvcr120d.def.in
index 658e5a314..a9552f0b5 100644
--- a/mingw-w64-crt/lib32/msvcr120d.def.in
+++ b/mingw-w64-crt/lib32/msvcr120d.def.in
@@ -1928,7 +1928,7 @@ atan2
 atanh
 atanhf
 atanhl
-atexit
+atexit DATA
 atof
 atoi
 atol
diff --git a/mingw-w64-crt/lib32/msvcr70.def b/mingw-w64-crt/lib32/msvcr70.def
index 5ec73e781..3d0275339 100644
--- a/mingw-w64-crt/lib32/msvcr70.def
+++ b/mingw-w64-crt/lib32/msvcr70.def
@@ -709,7 +709,7 @@ asctime
 asin
 atan
 atan2
-atexit
+atexit DATA
 atof
 atoi
 atol
diff --git a/mingw-w64-crt/lib32/msvcr71.def b/mingw-w64-crt/lib32/msvcr71.def
index 1db6d0b58..796fe52c5 100644
--- a/mingw-w64-crt/lib32/msvcr71.def
+++ b/mingw-w64-crt/lib32/msvcr71.def
@@ -704,7 +704,7 @@ asctime
 asin
 atan
 atan2
-atexit
+atexit DATA
 atof
 atoi
 atol
diff --git a/mingw-w64-crt/lib32/msvcrt10.def b/mingw-w64-crt/lib32/msvcrt10.def
index 5a3edf6e6..0265add70 100644
--- a/mingw-w64-crt/lib32/msvcrt10.def
+++ b/mingw-w64-crt/lib32/msvcrt10.def
@@ -1112,7 +1112,7 @@ asctime
 asin
 atan
 atan2
-atexit
+atexit DATA
 atof
 atoi
 atol
diff --git a/mingw-w64-crt/lib32/msvcrt20.def b/mingw-w64-crt/lib32/msvcrt20.def
index 48d0487b9..e0e3897ce 100644
--- a/mingw-w64-crt/lib32/msvcrt20.def
+++ b/mingw-w64-crt/lib32/msvcrt20.def
@@ -1380,7 +1380,7 @@ asctime
 asin
 atan
 atan2
-atexit
+atexit DATA
 atof
 atoi
 atol
diff --git a/mingw-w64-crt/lib32/msvcrt40.def b/mingw-w64-crt/lib32/msvcrt40.def
index 648f792df..5abc34469 100644
--- a/mingw-w64-crt/lib32/msvcrt40.def
+++ b/mingw-w64-crt/lib32/msvcrt40.def
@@ -1464,7 +1464,7 @@ asctime
 asin
 atan
 atan2
-atexit
+atexit DATA
 atof
 atoi
 atol
diff --git a/mingw-w64-crt/lib64/msvcr120.def.in 
b/mingw-w64-crt/lib64/msvcr120.def.in
index 0710c6bfb..a37df574d 100644
--- a/mingw-w64-crt/lib64/msvcr120.def.in
+++ b/mingw-w64-crt/lib64/msvcr120.def.in
@@ -1803,7 +1803,7 @@ atanf
 atanh
 atanhf
 atanhl
-atexit
+atexit DATA
 atof
 atoi
 atol
diff --git a/mingw-w64-crt/lib64/msvcr120d.def.in 
b/mingw-w64-crt/lib64/msvcr120d.def.in
index 4f2d65ee1..98a7b5f1d 100644
--- a/mingw-w64-crt/lib64/msvcr120d.def.in
+++ b/mingw-w64-crt/lib64/msvcr120d.def.in
@@ -1867,7 +1867,7 @@ atanf
 atanh
 atanhf
 atanhl
-atexit
+atexit DATA
 atof
 atoi
 atol
diff --git a/mingw-w64-crt/libarm32/kernelbase.def 
b/mingw-w64-crt/libarm32/kernelbase.def
index 954ea2dc1..d6a487db1 100644
--- a/mingw-w64-crt/libarm32/kernelbase.def
+++ b/mingw-w64-crt/libarm32/kernelbase.def
@@ -1889,7 +1889,7 @@ _invalid_parameter
 _onexit
 _purecall
 _time64
-atexit
+atexit DATA
 exit
 hgets
 hwprintf
diff --git a/mingw-w64-crt/libarm32/msvcr110.def 
b/mingw-w64-crt/libarm32/msvcr110.def
index 0b4855db8..e9835df42 100644
--- a/mingw-w64-crt/libarm32/msvcr110.def
+++ b/mingw-w64-crt/libarm32/msvcr110.def
@@ -1392,7 +1392,7 @@ atan
 atan2
 atan2f
 atanf
-atexit
+atexit DATA
 atof
 atoi
 atol
diff --git a/mingw-w64-crt/libarm32/msvcr120_clr0400.def 
b/mingw-w64-crt/libarm32/msvcr120_clr0400.def
index a1b3f7f30..a778c7ebf 100644
--- a/mingw-w64-crt/libarm32/msvcr120_clr0400.def
+++ b/mingw-w64-crt/libarm32/msvcr120_clr0400.def
@@ -1391,7 +1391,7 @@ atan
 atan2
 atan2f
 atanf
-atexit
+atexit DATA
 atof
 atoi
 atol
-- 
2.37.3

From d9f001979ec136f287c8f9d7209a6d9198a062b9 Mon Sep 17 00:00:00 2001
From: LIU Hao <[email protected]>
Date: Fri, 7 Oct 2022 22:46:50 +0800
Subject: [PATCH 2/3] crt: Provide wrappers for `*exit()` in libmingwex instead
 of import libraries

This should have no effect on functionality, but allows further
customization of them.

Signed-off-by: LIU Hao <[email protected]>
---
 mingw-w64-crt/Makefile.am                     |  2 +-
 mingw-w64-crt/crt/exit_wrappers.c             | 37 +++++++++++++++++++
 .../api-ms-win-crt-runtime-l1-1-0.def.in      |  8 ++--
 mingw-w64-crt/lib-common/msvcr120_app.def.in  |  4 +-
 mingw-w64-crt/lib-common/msvcrt.def.in        |  4 +-
 mingw-w64-crt/lib-common/ucrtbase.def.in      |  8 ++--
 mingw-w64-crt/lib32/crtdll.def                |  4 +-
 mingw-w64-crt/lib32/msvcr100.def.in           |  4 +-
 mingw-w64-crt/lib32/msvcr110.def.in           |  4 +-
 mingw-w64-crt/lib32/msvcr120.def.in           |  4 +-
 mingw-w64-crt/lib32/msvcr120d.def.in          |  4 +-
 mingw-w64-crt/lib32/msvcr70.def               |  4 +-
 mingw-w64-crt/lib32/msvcr71.def               |  4 +-
 mingw-w64-crt/lib32/msvcr80.def.in            |  4 +-
 mingw-w64-crt/lib32/msvcr90.def.in            |  4 +-
 mingw-w64-crt/lib32/msvcr90d.def.in           |  4 +-
 mingw-w64-crt/lib32/msvcrt10.def              |  4 +-
 mingw-w64-crt/lib32/msvcrt20.def              |  4 +-
 mingw-w64-crt/lib32/msvcrt40.def              |  4 +-
 mingw-w64-crt/lib64/msvcr100.def.in           |  4 +-
 mingw-w64-crt/lib64/msvcr110.def.in           |  4 +-
 mingw-w64-crt/lib64/msvcr120.def.in           |  4 +-
 mingw-w64-crt/lib64/msvcr120d.def.in          |  4 +-
 mingw-w64-crt/lib64/msvcr80.def.in            |  4 +-
 mingw-w64-crt/lib64/msvcr90.def.in            |  4 +-
 mingw-w64-crt/lib64/msvcr90d.def.in           |  4 +-
 mingw-w64-crt/libarm32/kernelbase.def         |  4 +-
 mingw-w64-crt/libarm32/msvcr110.def           |  4 +-
 mingw-w64-crt/libarm32/msvcr120_clr0400.def   |  4 +-
 29 files changed, 96 insertions(+), 59 deletions(-)
 create mode 100644 mingw-w64-crt/crt/exit_wrappers.c

diff --git a/mingw-w64-crt/Makefile.am b/mingw-w64-crt/Makefile.am
index 053eab3cf..6dbac2339 100644
--- a/mingw-w64-crt/Makefile.am
+++ b/mingw-w64-crt/Makefile.am
@@ -127,7 +127,7 @@ src_libmingw32=include/oscalls.h include/internal.h 
include/sect_attribs.h \
   crt/usermatherr.c   \
   crt/xtxtmode.c      crt/crt_handler.c    \
   crt/tlsthrd.c       crt/tlsmthread.c     crt/tlsmcrt.c   \
-  crt/cxa_atexit.c    crt/cxa_thread_atexit.c crt/tls_atexit.c
+  crt/cxa_atexit.c    crt/cxa_thread_atexit.c crt/tls_atexit.c  
crt/exit_wrappers.c
 
 src_libscrnsave=libsrc/scrnsave.c
 src_libscrnsavw=libsrc/scrnsave.c
diff --git a/mingw-w64-crt/crt/exit_wrappers.c 
b/mingw-w64-crt/crt/exit_wrappers.c
new file mode 100644
index 000000000..714395dec
--- /dev/null
+++ b/mingw-w64-crt/crt/exit_wrappers.c
@@ -0,0 +1,37 @@
+/**
+ * This file has no copyright assigned and is placed in the Public Domain.
+ * This file is part of the mingw-w64 runtime package.
+ * No warranty is given; refer to the file DISCLAIMER.PD within this package.
+ */
+
+#include <stdlib.h>
+
+/* `exit()`, C89  */
+extern void (*__MINGW_IMP_SYMBOL(exit))(int) __attribute__((__noreturn__));
+
+void exit(int status) {
+  (*__MINGW_IMP_SYMBOL(exit))(status);
+}
+
+/* `_exit()`, POSIX  */
+extern void (*__MINGW_IMP_SYMBOL(_exit))(int) __attribute__((__noreturn__));
+
+void _exit(int status) {
+  (*__MINGW_IMP_SYMBOL(_exit))(status);
+}
+
+#ifdef _UCRT
+/* `quick_exit()`, C99  */
+extern void (*__MINGW_IMP_SYMBOL(quick_exit))(int) 
__attribute__((__noreturn__));
+
+void quick_exit(int status) {
+  (*__MINGW_IMP_SYMBOL(quick_exit))(status);
+}
+
+/* `_Exit()`, C99  */
+extern void (*__MINGW_IMP_SYMBOL(_Exit))(int) __attribute__((__noreturn__));
+
+void _Exit(int status) {
+  (*__MINGW_IMP_SYMBOL(_Exit))(status);
+}
+#endif  /* _UCRT  */
diff --git a/mingw-w64-crt/lib-common/api-ms-win-crt-runtime-l1-1-0.def.in 
b/mingw-w64-crt/lib-common/api-ms-win-crt-runtime-l1-1-0.def.in
index ea310d426..33e4f5504 100644
--- a/mingw-w64-crt/lib-common/api-ms-win-crt-runtime-l1-1-0.def.in
+++ b/mingw-w64-crt/lib-common/api-ms-win-crt-runtime-l1-1-0.def.in
@@ -4,7 +4,7 @@ EXPORTS
 
 #include "func.def.in"
 
-_Exit
+_Exit DATA
 F_I386(__control87_2)
 __doserrno
 __fpe_flt_rounds
@@ -42,7 +42,7 @@ _endthread
 _endthreadex
 _errno
 _execute_onexit_table
-_exit
+_exit DATA
 F_NON_I386(_fpieee_flt)
 ; DATA added manually
 _fpreset DATA
@@ -96,7 +96,7 @@ _wcserror_s
 _wperror
 _wsystem
 abort
-exit
+exit DATA
 ; Don't use the float env functions from UCRT; fesetround doesn't seem to have
 ; any effect on the FPU control word as required by other libmingwex math
 ; routines.
@@ -110,7 +110,7 @@ fesetexceptflag DATA
 fesetround DATA
 fetestexcept DATA
 perror
-quick_exit
+quick_exit DATA
 raise
 set_terminate
 signal
diff --git a/mingw-w64-crt/lib-common/msvcr120_app.def.in 
b/mingw-w64-crt/lib-common/msvcr120_app.def.in
index ddb407d00..33f2e9345 100644
--- a/mingw-w64-crt/lib-common/msvcr120_app.def.in
+++ b/mingw-w64-crt/lib-common/msvcr120_app.def.in
@@ -1080,7 +1080,7 @@ F_ARM32(_execv)
 F_ARM32(_execve)
 F_ARM32(_execvp)
 F_ARM32(_execvpe)
-_exit
+_exit DATA
 F_X86_ANY(_exit_app)
 _expand
 F_X86_ANY(_fclose_nolock)
@@ -2143,7 +2143,7 @@ erfcl
 erff
 erfl
 #endif
-exit
+exit DATA
 exp
 exp2
 exp2f
diff --git a/mingw-w64-crt/lib-common/msvcrt.def.in 
b/mingw-w64-crt/lib-common/msvcrt.def.in
index 942c4c4eb..d7359f35a 100644
--- a/mingw-w64-crt/lib-common/msvcrt.def.in
+++ b/mingw-w64-crt/lib-common/msvcrt.def.in
@@ -481,7 +481,7 @@ _execv
 _execve
 _execvp
 _execvpe
-_exit
+_exit DATA
 _expand
 F_ARM_ANY(_expand_dbg)
 _fcloseall
@@ -1342,7 +1342,7 @@ F_NON_I386(coshf DATA)
 ctime
 difftime
 div
-exit
+exit DATA
 exp F_X86_ANY(DATA)
 F_NON_I386(expf F_X86_ANY(DATA))
 F_ARM_ANY(expl == exp)
diff --git a/mingw-w64-crt/lib-common/ucrtbase.def.in 
b/mingw-w64-crt/lib-common/ucrtbase.def.in
index a90fd72b7..ae3d3f95a 100644
--- a/mingw-w64-crt/lib-common/ucrtbase.def.in
+++ b/mingw-w64-crt/lib-common/ucrtbase.def.in
@@ -30,7 +30,7 @@ _CreateFrameInfo
 F_I386(_CxxThrowException@8)
 F_NON_I386(_CxxThrowException)
 F_I386(_EH_prolog)
-_Exit
+_Exit DATA
 _FCbuild
 _FCmulcc
 _FCmulcr
@@ -299,7 +299,7 @@ _execv
 _execve
 _execvp
 _execvpe
-_exit
+_exit DATA
 _expand
 _fclose_nolock
 _fcloseall
@@ -2305,7 +2305,7 @@ erfcf
 erfcl F_X86_ANY(DATA)
 erff
 erfl F_X86_ANY(DATA)
-exit
+exit DATA
 exp F_X86_ANY(DATA)
 exp2
 exp2f
@@ -2500,7 +2500,7 @@ putwc
 putwchar
 qsort
 qsort_s
-quick_exit
+quick_exit DATA
 raise
 rand
 rand_s
diff --git a/mingw-w64-crt/lib32/crtdll.def b/mingw-w64-crt/lib32/crtdll.def
index fed70ffa6..ab5cd34f3 100644
--- a/mingw-w64-crt/lib32/crtdll.def
+++ b/mingw-w64-crt/lib32/crtdll.def
@@ -266,7 +266,7 @@ _execv
 _execve
 _execvp
 _execvpe
-_exit
+_exit DATA
 _expand
 _fcloseall
 _fcvt
@@ -552,7 +552,7 @@ ctime DATA
 ;_ctime32 = ctime
 difftime
 div
-exit
+exit DATA
 exp DATA
 fabs DATA
 fclose
diff --git a/mingw-w64-crt/lib32/msvcr100.def.in 
b/mingw-w64-crt/lib32/msvcr100.def.in
index 8e8dfb460..0772af371 100644
--- a/mingw-w64-crt/lib32/msvcr100.def.in
+++ b/mingw-w64-crt/lib32/msvcr100.def.in
@@ -831,7 +831,7 @@ _execv
 _execve
 _execvp
 _execvpe
-_exit
+_exit DATA
 _expand
 _fclose_nolock
 _fcloseall
@@ -1691,7 +1691,7 @@ cos DATA
 ; If we implement cosh too, we can set it to DATA only.
 cosh
 div
-exit
+exit DATA
 exp DATA
 fabs DATA
 fclose
diff --git a/mingw-w64-crt/lib32/msvcr110.def.in 
b/mingw-w64-crt/lib32/msvcr110.def.in
index b864009b6..c0d1a9c1f 100644
--- a/mingw-w64-crt/lib32/msvcr110.def.in
+++ b/mingw-w64-crt/lib32/msvcr110.def.in
@@ -954,7 +954,7 @@ _execv
 _execve
 _execvp
 _execvpe
-_exit
+_exit DATA
 _expand
 _fclose_nolock
 _fcloseall
@@ -1824,7 +1824,7 @@ cos DATA
 ; If we implement cosh, we can set it to DATA only.
 cosh
 div
-exit
+exit DATA
 exp DATA
 fabs DATA
 fclose
diff --git a/mingw-w64-crt/lib32/msvcr120.def.in 
b/mingw-w64-crt/lib32/msvcr120.def.in
index 82adab07b..af92ebfcf 100644
--- a/mingw-w64-crt/lib32/msvcr120.def.in
+++ b/mingw-w64-crt/lib32/msvcr120.def.in
@@ -973,7 +973,7 @@ _execv
 _execve
 _execvp
 _execvpe
-_exit
+_exit DATA
 _expand
 _fclose_nolock
 _fcloseall
@@ -1958,7 +1958,7 @@ erfcf
 erfcl
 erff
 erfl
-exit
+exit DATA
 exp
 exp2
 exp2f
diff --git a/mingw-w64-crt/lib32/msvcr120d.def.in 
b/mingw-w64-crt/lib32/msvcr120d.def.in
index a9552f0b5..b77a3661d 100644
--- a/mingw-w64-crt/lib32/msvcr120d.def.in
+++ b/mingw-w64-crt/lib32/msvcr120d.def.in
@@ -1026,7 +1026,7 @@ _execv
 _execve
 _execvp
 _execvpe
-_exit
+_exit DATA
 _expand
 _expand_dbg
 _fclose_nolock
@@ -2025,7 +2025,7 @@ erfcf
 erfcl
 erff
 erfl
-exit
+exit DATA
 exp
 exp2
 exp2f
diff --git a/mingw-w64-crt/lib32/msvcr70.def b/mingw-w64-crt/lib32/msvcr70.def
index 3d0275339..c10830281 100644
--- a/mingw-w64-crt/lib32/msvcr70.def
+++ b/mingw-w64-crt/lib32/msvcr70.def
@@ -312,7 +312,7 @@ _execv
 _execve
 _execvp
 _execvpe
-_exit
+_exit DATA
 _expand
 _fcloseall
 _fcvt
@@ -723,7 +723,7 @@ cosh
 ctime
 difftime
 div
-exit
+exit DATA
 exp
 fabs
 fclose
diff --git a/mingw-w64-crt/lib32/msvcr71.def b/mingw-w64-crt/lib32/msvcr71.def
index 796fe52c5..53d2e6a14 100644
--- a/mingw-w64-crt/lib32/msvcr71.def
+++ b/mingw-w64-crt/lib32/msvcr71.def
@@ -305,7 +305,7 @@ _execv
 _execve
 _execvp
 _execvpe
-_exit
+_exit DATA
 _expand
 _fcloseall
 _fcvt
@@ -718,7 +718,7 @@ cosh
 ctime
 difftime
 div
-exit
+exit DATA
 exp
 fabs
 fclose
diff --git a/mingw-w64-crt/lib32/msvcr80.def.in 
b/mingw-w64-crt/lib32/msvcr80.def.in
index bb1ec8444..639befe4b 100644
--- a/mingw-w64-crt/lib32/msvcr80.def.in
+++ b/mingw-w64-crt/lib32/msvcr80.def.in
@@ -162,7 +162,7 @@ _execv
 _execve
 _execvp
 _execvpe
-_exit
+_exit DATA
 _expand
 _fcloseall
 _fcvt
@@ -588,7 +588,7 @@ _ctime32
 ctime == _ctime32
 difftime
 div
-exit
+exit DATA
 exp DATA
 fabs DATA
 fclose
diff --git a/mingw-w64-crt/lib32/msvcr90.def.in 
b/mingw-w64-crt/lib32/msvcr90.def.in
index 62789337b..83d818703 100644
--- a/mingw-w64-crt/lib32/msvcr90.def.in
+++ b/mingw-w64-crt/lib32/msvcr90.def.in
@@ -458,7 +458,7 @@ _execv
 _execve
 _execvp
 _execvpe
-_exit
+_exit DATA
 _expand
 _fclose_nolock
 _fcloseall
@@ -1327,7 +1327,7 @@ cos DATA
 ; If we have cosh implementation, we can set it to DATA only.
 cosh
 div
-exit
+exit DATA
 exp DATA
 fabs DATA
 fclose
diff --git a/mingw-w64-crt/lib32/msvcr90d.def.in 
b/mingw-w64-crt/lib32/msvcr90d.def.in
index 1175bfec1..79ed6351f 100644
--- a/mingw-w64-crt/lib32/msvcr90d.def.in
+++ b/mingw-w64-crt/lib32/msvcr90d.def.in
@@ -515,7 +515,7 @@ _execv
 _execve
 _execvp
 _execvpe
-_exit
+_exit DATA
 _expand
 _expand_dbg
 _fclose_nolock
@@ -1399,7 +1399,7 @@ cos DATA
 ; If we implement cosh too, we can set it to DATA only.
 cosh
 div
-exit
+exit DATA
 exp DATA
 fabs DATA
 fclose
diff --git a/mingw-w64-crt/lib32/msvcrt10.def b/mingw-w64-crt/lib32/msvcrt10.def
index 0265add70..6fcb35b19 100644
--- a/mingw-w64-crt/lib32/msvcrt10.def
+++ b/mingw-w64-crt/lib32/msvcrt10.def
@@ -943,7 +943,7 @@ _execv
 _execve
 _execvp
 _execvpe
-_exit
+_exit DATA
 _expand
 _fcloseall
 _fcvt
@@ -1126,7 +1126,7 @@ cosh
 ctime
 difftime
 div
-exit
+exit DATA
 exp
 fabs
 fclose
diff --git a/mingw-w64-crt/lib32/msvcrt20.def b/mingw-w64-crt/lib32/msvcrt20.def
index e0e3897ce..de320ec22 100644
--- a/mingw-w64-crt/lib32/msvcrt20.def
+++ b/mingw-w64-crt/lib32/msvcrt20.def
@@ -1013,7 +1013,7 @@ _execv
 _execve
 _execvp
 _execvpe
-_exit
+_exit DATA
 _expand
 _fcloseall
 _fcvt
@@ -1394,7 +1394,7 @@ cosh
 ctime
 difftime
 div
-exit
+exit DATA
 exp
 fabs
 fclose
diff --git a/mingw-w64-crt/lib32/msvcrt40.def b/mingw-w64-crt/lib32/msvcrt40.def
index 5abc34469..e07065ecb 100644
--- a/mingw-w64-crt/lib32/msvcrt40.def
+++ b/mingw-w64-crt/lib32/msvcrt40.def
@@ -1112,7 +1112,7 @@ _execv
 _execve
 _execvp
 _execvpe
-_exit
+_exit DATA
 _expand
 _fcloseall
 _fcvt
@@ -1478,7 +1478,7 @@ cosh
 ctime
 difftime
 div
-exit
+exit DATA
 exp
 fabs
 fclose
diff --git a/mingw-w64-crt/lib64/msvcr100.def.in 
b/mingw-w64-crt/lib64/msvcr100.def.in
index aab982691..e91bdaf86 100644
--- a/mingw-w64-crt/lib64/msvcr100.def.in
+++ b/mingw-w64-crt/lib64/msvcr100.def.in
@@ -786,7 +786,7 @@ _execv
 _execve
 _execvp
 _execvpe
-_exit
+_exit DATA
 _expand
 _fclose_nolock
 _fcloseall
@@ -1644,7 +1644,7 @@ cosf DATA
 cosh
 coshf DATA
 div
-exit
+exit DATA
 exp DATA
 expf DATA
 fabs DATA
diff --git a/mingw-w64-crt/lib64/msvcr110.def.in 
b/mingw-w64-crt/lib64/msvcr110.def.in
index 60304f9fd..d7d8b90d9 100644
--- a/mingw-w64-crt/lib64/msvcr110.def.in
+++ b/mingw-w64-crt/lib64/msvcr110.def.in
@@ -911,7 +911,7 @@ _execv
 _execve
 _execvp
 _execvpe
-_exit
+_exit DATA
 _expand
 _fclose_nolock
 _fcloseall
@@ -1768,7 +1768,7 @@ cosf
 cosh
 coshf
 div
-exit
+exit DATA
 exp
 expf
 fabs
diff --git a/mingw-w64-crt/lib64/msvcr120.def.in 
b/mingw-w64-crt/lib64/msvcr120.def.in
index a37df574d..f63e9f09e 100644
--- a/mingw-w64-crt/lib64/msvcr120.def.in
+++ b/mingw-w64-crt/lib64/msvcr120.def.in
@@ -927,7 +927,7 @@ _execv
 _execve
 _execvp
 _execvpe
-_exit
+_exit DATA
 _expand
 _fclose_nolock
 _fcloseall
@@ -1903,7 +1903,7 @@ erfcf
 erfcl
 erff
 erfl
-exit
+exit DATA
 exp
 exp2
 exp2f
diff --git a/mingw-w64-crt/lib64/msvcr120d.def.in 
b/mingw-w64-crt/lib64/msvcr120d.def.in
index 98a7b5f1d..8298c5fff 100644
--- a/mingw-w64-crt/lib64/msvcr120d.def.in
+++ b/mingw-w64-crt/lib64/msvcr120d.def.in
@@ -978,7 +978,7 @@ _execv
 _execve
 _execvp
 _execvpe
-_exit
+_exit DATA
 _expand
 _expand_dbg
 _fclose_nolock
@@ -1967,7 +1967,7 @@ erfcf
 erfcl
 erff
 erfl
-exit
+exit DATA
 exp
 exp2
 exp2f
diff --git a/mingw-w64-crt/lib64/msvcr80.def.in 
b/mingw-w64-crt/lib64/msvcr80.def.in
index 045052ec8..796f5ef09 100644
--- a/mingw-w64-crt/lib64/msvcr80.def.in
+++ b/mingw-w64-crt/lib64/msvcr80.def.in
@@ -250,7 +250,7 @@ _execv
 _execve
 _execvp
 _execvpe
-_exit
+_exit DATA
 _expand
 _fcloseall
 _fcvt
@@ -713,7 +713,7 @@ coshf
 _ctime32
 difftime
 div
-exit
+exit DATA
 exp DATA
 expf DATA
 fabs
diff --git a/mingw-w64-crt/lib64/msvcr90.def.in 
b/mingw-w64-crt/lib64/msvcr90.def.in
index c8cf9b220..e5e5f57a9 100644
--- a/mingw-w64-crt/lib64/msvcr90.def.in
+++ b/mingw-w64-crt/lib64/msvcr90.def.in
@@ -403,7 +403,7 @@ _execv
 _execve
 _execvp
 _execvpe
-_exit
+_exit DATA
 _expand
 _fclose_nolock
 _fcloseall
@@ -1266,7 +1266,7 @@ cosf DATA
 cosh
 coshf DATA
 div
-exit
+exit DATA
 exp DATA
 expf DATA
 fabs DATA
diff --git a/mingw-w64-crt/lib64/msvcr90d.def.in 
b/mingw-w64-crt/lib64/msvcr90d.def.in
index 2acdc3fcf..f1544774d 100644
--- a/mingw-w64-crt/lib64/msvcr90d.def.in
+++ b/mingw-w64-crt/lib64/msvcr90d.def.in
@@ -454,7 +454,7 @@ _execv
 _execve
 _execvp
 _execvpe
-_exit
+_exit DATA
 _expand
 _expand_dbg
 _fclose_nolock
@@ -1332,7 +1332,7 @@ cosf
 cosh
 coshf
 div
-exit
+exit DATA
 exp DATA
 expf DATA
 fabs
diff --git a/mingw-w64-crt/libarm32/kernelbase.def 
b/mingw-w64-crt/libarm32/kernelbase.def
index d6a487db1..f6626c5df 100644
--- a/mingw-w64-crt/libarm32/kernelbase.def
+++ b/mingw-w64-crt/libarm32/kernelbase.def
@@ -1882,7 +1882,7 @@ __wgetmainargs
 _amsg_exit
 _c_exit
 _cexit
-_exit
+_exit DATA
 _initterm
 _initterm_e
 _invalid_parameter
@@ -1890,7 +1890,7 @@ _onexit
 _purecall
 _time64
 atexit DATA
-exit
+exit DATA
 hgets
 hwprintf
 lstrcmp
diff --git a/mingw-w64-crt/libarm32/msvcr110.def 
b/mingw-w64-crt/libarm32/msvcr110.def
index e9835df42..0c052a4e7 100644
--- a/mingw-w64-crt/libarm32/msvcr110.def
+++ b/mingw-w64-crt/libarm32/msvcr110.def
@@ -574,7 +574,7 @@ _execv
 _execve
 _execvp
 _execvpe
-_exit
+_exit DATA
 _expand
 _fclose_nolock
 _fcloseall
@@ -1410,7 +1410,7 @@ cosf
 cosh
 coshf
 div
-exit
+exit DATA
 exp
 expf
 fabs
diff --git a/mingw-w64-crt/libarm32/msvcr120_clr0400.def 
b/mingw-w64-crt/libarm32/msvcr120_clr0400.def
index a778c7ebf..dcb34cca2 100644
--- a/mingw-w64-crt/libarm32/msvcr120_clr0400.def
+++ b/mingw-w64-crt/libarm32/msvcr120_clr0400.def
@@ -573,7 +573,7 @@ _execv
 _execve
 _execvp
 _execvpe
-_exit
+_exit DATA
 _expand
 _fclose_nolock
 _fcloseall
@@ -1409,7 +1409,7 @@ cosf
 cosh
 coshf
 div
-exit
+exit DATA
 exp
 expf
 fabs
-- 
2.37.3

From 5c2f6fb1ff821325c025a215f530ec99b95543d5 Mon Sep 17 00:00:00 2001
From: LIU Hao <[email protected]>
Date: Fri, 7 Oct 2022 23:18:46 +0800
Subject: [PATCH 3/3] crt: Implement standard-conforming termination support
 with mcfgthread

This commit implements these functions in accordance with the ISO C
standard and the Itanium C++ ABI (except for `atexit()` which behaves
in a per-module way like its old behavior, and also on Linux):

  * `atexit()`, C89
  * `exit()`, C89
  * `__cxa_atexit()`, Itanium C++ ABI
  * `_exit()`, POSIX
  * `_Exit()`, C99
  * `at_quick_exit()`, C99
  * `quick_exit()`, C99
  * `__cxa_at_quick_exit()`, GNU extension

Implementation details:

  1. An object with the name `__dso_handle` is defined for each
     module (EXE or DLL).
  2. Per-module cleanup callbacks should be registered with
     `__MCF_cxa_atexit()` or `__MCF_cxa_at_quick_exit()`, passing
     `&__dso_handle` as its third argument.
  3. When a process calls `exit()` or returns from `main()`,
     `__MCF_cxa_finalize(NULL)` is called, which executes all
     callbacks registered with `__MCF_cxa_atexit()` in reverse
     order.
  4. When a DLL is unloaded neither by calling `exit()` nor by
     returning from `main()` (in other words, by `FreeLibrary()`),
     `__MCF_cxa_finalize(&__dso_handle)`, which executes all
     callbacks registered with `__MCF_cxa_atexit()` with the same
     DSO handle in reverse order. Callbacks that have been
     registered with `__MCF_cxa_at_quick_exit()` are deleted.
  5. All standard I/O streams are flushed before the process
     terminates.

Signed-off-by: LIU Hao <[email protected]>
---
 mingw-w64-crt/Makefile.am             |  2 +-
 mingw-w64-crt/crt/crtdll.c            | 29 ++++++++++++++++++++++++++-
 mingw-w64-crt/crt/crtexe.c            | 14 +++++++++++++
 mingw-w64-crt/crt/cxa_at_quick_exit.c | 28 ++++++++++++++++++++++++++
 mingw-w64-crt/crt/cxa_atexit.c        | 19 ++++++++++++++++++
 mingw-w64-crt/crt/cxa_thread_atexit.c | 19 ++++++++++++++++++
 mingw-w64-crt/crt/exit_wrappers.c     | 19 ++++++++++++++++++
 mingw-w64-crt/crt/ucrtbase_compat.c   |  8 ++++++++
 8 files changed, 136 insertions(+), 2 deletions(-)
 create mode 100644 mingw-w64-crt/crt/cxa_at_quick_exit.c

diff --git a/mingw-w64-crt/Makefile.am b/mingw-w64-crt/Makefile.am
index 6dbac2339..a83ed0593 100644
--- a/mingw-w64-crt/Makefile.am
+++ b/mingw-w64-crt/Makefile.am
@@ -127,7 +127,7 @@ src_libmingw32=include/oscalls.h include/internal.h 
include/sect_attribs.h \
   crt/usermatherr.c   \
   crt/xtxtmode.c      crt/crt_handler.c    \
   crt/tlsthrd.c       crt/tlsmthread.c     crt/tlsmcrt.c   \
-  crt/cxa_atexit.c    crt/cxa_thread_atexit.c crt/tls_atexit.c  
crt/exit_wrappers.c
+  crt/cxa_atexit.c    crt/cxa_at_quick_exit.c  crt/cxa_thread_atexit.c 
crt/tls_atexit.c  crt/exit_wrappers.c
 
 src_libscrnsave=libsrc/scrnsave.c
 src_libscrnsavw=libsrc/scrnsave.c
diff --git a/mingw-w64-crt/crt/crtdll.c b/mingw-w64-crt/crt/crtdll.c
index 08cd5922a..87eb34ae9 100644
--- a/mingw-w64-crt/crt/crtdll.c
+++ b/mingw-w64-crt/crt/crtdll.c
@@ -31,6 +31,12 @@
 #endif
 #include <sect_attribs.h>
 #include <locale.h>
+#include <stdio.h>
+#ifdef __USING_MCFGTHREAD__
+#include <mcfgthread/cxa.h>
+#endif  /* __USING_MCFGTHREAD__  */
+
+extern HANDLE __dso_handle;
 
 extern void __cdecl _initterm(_PVFV *,_PVFV *);
 extern void __main ();
@@ -181,7 +187,14 @@ __DllMainCRTStartup (HANDLE hDllHandle, DWORD dwReason, 
LPVOID lpreserved)
          }
     }
   if (dwReason == DLL_PROCESS_ATTACH)
-    __main ();
+    {
+#ifdef __USING_MCFGTHREAD__
+      /* Register `fflush(NULL)` before user-defined constructors, so it
+       * will be executed after all user-defined destructors.  */
+      __MCF_cxa_atexit ((__MCF_cxa_dtor_cdecl*)(intptr_t) fflush, NULL, 
&__dso_handle);
+#endif
+      __main ();
+    }
   retcode = DllMain(hDllHandle,dwReason,lpreserved);
   if (dwReason == DLL_PROCESS_ATTACH && ! retcode)
     {
@@ -195,6 +208,16 @@ __DllMainCRTStartup (HANDLE hDllHandle, DWORD dwReason, 
LPVOID lpreserved)
        if (_CRT_INIT (hDllHandle, dwReason, lpreserved) == FALSE)
          retcode = FALSE;
     }
+#ifdef __USING_MCFGTHREAD__
+  if (dwReason == DLL_PROCESS_DETACH && lpreserved == NULL)
+    {
+      /* Call `__cxa_finalize(dso_handle)` if the library is unloaded
+       * dynamically. This conforms to the Itanium C++ ABI. Note it is
+       * not called in case of process termination, where a call to
+       * `__cxa_finalize(NULL)` shall have been made instead.  */
+      __MCF_cxa_finalize (&__dso_handle);
+    }
+#endif
 i__leave:
   __native_dllmain_reason = UINT_MAX;
   return retcode ;
@@ -203,7 +226,11 @@ i__leave:
 
 int __cdecl atexit (_PVFV func)
 {
+#ifdef __USING_MCFGTHREAD__
+    return __MCF_cxa_atexit ((__MCF_cxa_dtor_cdecl*)(intptr_t) func, NULL, 
&__dso_handle);
+#else
     return _register_onexit_function(&atexit_table, (_onexit_t)func);
+#endif
 }
 
 char __mingw_module_is_dll = 1;
diff --git a/mingw-w64-crt/crt/crtexe.c b/mingw-w64-crt/crt/crtexe.c
index 65303f818..1b705ac3e 100644
--- a/mingw-w64-crt/crt/crtexe.c
+++ b/mingw-w64-crt/crt/crtexe.c
@@ -20,6 +20,10 @@
 #include <tchar.h>
 #include <sect_attribs.h>
 #include <locale.h>
+#include <stdio.h>
+#ifdef __USING_MCFGTHREAD__
+#include <mcfgthread/cxa.h>
+#endif  /* __USING_MCFGTHREAD__  */
 
 #if defined(__SEH__) && (!defined(__clang__) || __clang_major__ >= 7)
 #define SEH_INLINE_ASM
@@ -52,6 +56,7 @@ int *__cdecl __p__commode(void);
 extern int _fmode;
 extern int _commode;
 extern int _dowildcard;
+extern HANDLE __dso_handle;
 
 extern _CRTIMP void __cdecl _initterm(_PVFV *, _PVFV *);
 
@@ -318,6 +323,11 @@ __tmainCRTStartup (void)
                                    StartupInfo.wShowWindow : SW_SHOWDEFAULT;
       }
     duplicate_ppstrings (argc, &argv);
+#ifdef __USING_MCFGTHREAD__
+      /* Register `fflush(NULL)` before user-defined constructors, so it
+       * will be executed after all user-defined destructors.  */
+      __MCF_cxa_atexit ((__MCF_cxa_dtor_cdecl*)(intptr_t) fflush, NULL, 
&__dso_handle);
+#endif
     __main ();
 #ifdef WPRFLAG
     __winitenv = envp;
@@ -424,7 +434,11 @@ static void duplicate_ppstrings (int ac, char ***av)
 
 int __cdecl atexit (_PVFV func)
 {
+#ifdef __USING_MCFGTHREAD__
+    return __MCF_cxa_atexit ((__MCF_cxa_dtor_cdecl*)(intptr_t) func, NULL, 
&__dso_handle);
+#else
     return _onexit((_onexit_t)func) ? 0 : -1;
+#endif
 }
 
 char __mingw_module_is_dll = 0;
diff --git a/mingw-w64-crt/crt/cxa_at_quick_exit.c 
b/mingw-w64-crt/crt/cxa_at_quick_exit.c
new file mode 100644
index 000000000..8fc6d594a
--- /dev/null
+++ b/mingw-w64-crt/crt/cxa_at_quick_exit.c
@@ -0,0 +1,28 @@
+/**
+ * This file has no copyright assigned and is placed in the Public Domain.
+ * This file is part of the mingw-w64 runtime package.
+ * No warranty is given; refer to the file DISCLAIMER.PD within this package.
+ */
+
+typedef void (__thiscall * dtor_fn)(void*);
+int __cxa_at_quick_exit(dtor_fn dtor, void *obj, void *dso);
+
+#ifdef __USING_MCFGTHREAD__
+
+#include <mcfgthread/cxa.h>
+
+typedef void* HANDLE;
+extern HANDLE __dso_handle;
+
+int __cxa_at_quick_exit(dtor_fn dtor, void *obj, void *dso) {
+  /* This statically-linked wrapper always references the calling
+   * module itself.  */
+  (void) dso;
+  return __MCF_cxa_at_quick_exit(dtor, obj, &__dso_handle);
+}
+
+#else  /* __USING_MCFGTHREAD__  */
+
+/* TODO: unimplemented  */
+
+#endif  /* __USING_MCFGTHREAD__  */
diff --git a/mingw-w64-crt/crt/cxa_atexit.c b/mingw-w64-crt/crt/cxa_atexit.c
index c4b5be111..ecddfbdca 100644
--- a/mingw-w64-crt/crt/cxa_atexit.c
+++ b/mingw-w64-crt/crt/cxa_atexit.c
@@ -6,8 +6,27 @@
 
 typedef void (__thiscall * dtor_fn)(void*);
 int __cxa_atexit(dtor_fn dtor, void *obj, void *dso);
+
+#ifdef __USING_MCFGTHREAD__
+
+#include <mcfgthread/cxa.h>
+
+typedef void* HANDLE;
+extern HANDLE __dso_handle;
+
+int __cxa_atexit(dtor_fn dtor, void *obj, void *dso) {
+  /* This statically-linked wrapper always references the calling
+   * module itself.  */
+  (void) dso;
+  return __MCF_cxa_atexit(dtor, obj, &__dso_handle);
+}
+
+#else  /* __USING_MCFGTHREAD__  */
+
 int __mingw_cxa_atexit(dtor_fn dtor, void *obj, void *dso);
 
 int __cxa_atexit(dtor_fn dtor, void *obj, void *dso) {
   return __mingw_cxa_atexit(dtor, obj, dso);
 }
+
+#endif  /* __USING_MCFGTHREAD__  */
diff --git a/mingw-w64-crt/crt/cxa_thread_atexit.c 
b/mingw-w64-crt/crt/cxa_thread_atexit.c
index 3078c2444..1d93c3fa8 100644
--- a/mingw-w64-crt/crt/cxa_thread_atexit.c
+++ b/mingw-w64-crt/crt/cxa_thread_atexit.c
@@ -6,8 +6,27 @@
 
 typedef void (__thiscall * dtor_fn)(void*);
 int __cxa_thread_atexit(dtor_fn dtor, void *obj, void *dso);
+
+#ifdef __USING_MCFGTHREAD__
+
+#include <mcfgthread/cxa.h>
+
+typedef void* HANDLE;
+extern HANDLE __dso_handle;
+
+int __cxa_thread_atexit(dtor_fn dtor, void *obj, void *dso) {
+  /* This statically-linked wrapper always references the calling
+   * module itself.  */
+  (void) dso;
+  return __MCF_cxa_thread_atexit(dtor, obj, &__dso_handle);
+}
+
+#else  /* __USING_MCFGTHREAD__  */
+
 int __mingw_cxa_thread_atexit(dtor_fn dtor, void *obj, void *dso);
 
 int __cxa_thread_atexit(dtor_fn dtor, void *obj, void *dso) {
   return __mingw_cxa_thread_atexit(dtor, obj, dso);
 }
+
+#endif  /* __USING_MCFGTHREAD__  */
diff --git a/mingw-w64-crt/crt/exit_wrappers.c 
b/mingw-w64-crt/crt/exit_wrappers.c
index 714395dec..3be71e492 100644
--- a/mingw-w64-crt/crt/exit_wrappers.c
+++ b/mingw-w64-crt/crt/exit_wrappers.c
@@ -5,19 +5,30 @@
  */
 
 #include <stdlib.h>
+#ifdef __USING_MCFGTHREAD__
+#include <mcfgthread/exit.h>
+#endif  /* __USING_MCFGTHREAD__  */
 
 /* `exit()`, C89  */
 extern void (*__MINGW_IMP_SYMBOL(exit))(int) __attribute__((__noreturn__));
 
 void exit(int status) {
+#ifdef __USING_MCFGTHREAD__
+  __MCF_exit(status);
+#else
   (*__MINGW_IMP_SYMBOL(exit))(status);
+#endif
 }
 
 /* `_exit()`, POSIX  */
 extern void (*__MINGW_IMP_SYMBOL(_exit))(int) __attribute__((__noreturn__));
 
 void _exit(int status) {
+#ifdef __USING_MCFGTHREAD__
+  __MCF__Exit(status);
+#else
   (*__MINGW_IMP_SYMBOL(_exit))(status);
+#endif
 }
 
 #ifdef _UCRT
@@ -25,13 +36,21 @@ void _exit(int status) {
 extern void (*__MINGW_IMP_SYMBOL(quick_exit))(int) 
__attribute__((__noreturn__));
 
 void quick_exit(int status) {
+#ifdef __USING_MCFGTHREAD__
+  __MCF_quick_exit(status);
+#else
   (*__MINGW_IMP_SYMBOL(quick_exit))(status);
+#endif
 }
 
 /* `_Exit()`, C99  */
 extern void (*__MINGW_IMP_SYMBOL(_Exit))(int) __attribute__((__noreturn__));
 
 void _Exit(int status) {
+#ifdef __USING_MCFGTHREAD__
+  __MCF__Exit(status);
+#else
   (*__MINGW_IMP_SYMBOL(_Exit))(status);
+#endif
 }
 #endif  /* _UCRT  */
diff --git a/mingw-w64-crt/crt/ucrtbase_compat.c 
b/mingw-w64-crt/crt/ucrtbase_compat.c
index 02910ff2f..9ac99f970 100644
--- a/mingw-w64-crt/crt/ucrtbase_compat.c
+++ b/mingw-w64-crt/crt/ucrtbase_compat.c
@@ -22,6 +22,9 @@
 #include <stdio.h>
 #include <time.h>
 #include <corecrt_startup.h>
+#ifdef __USING_MCFGTHREAD__
+#include <mcfgthread/cxa.h>
+#endif  /* __USING_MCFGTHREAD__  */
 
 #undef __getmainargs
 #undef __wgetmainargs
@@ -56,6 +59,7 @@ _CRTIMP int __cdecl _configure_wide_argv(int mode);
 _CRTIMP int __cdecl _set_new_mode(int _NewMode);
 
 extern char __mingw_module_is_dll;
+extern HANDLE __dso_handle;
 
 
 // Wrappers with legacy msvcrt.dll style API, based on the new ucrtbase.dll 
functions.
@@ -92,12 +96,16 @@ _onexit_t __cdecl (*__MINGW_IMP_SYMBOL(_onexit))(_onexit_t 
func) = _onexit;
 
 int __cdecl at_quick_exit(void (__cdecl *func)(void))
 {
+#ifdef __USING_MCFGTHREAD__
+  return __MCF_cxa_at_quick_exit ((__MCF_cxa_dtor_cdecl*)(intptr_t) func, 
NULL, &__dso_handle);
+#else  /* __USING_MCFGTHREAD__  */
   // In a DLL, we can't register a function with _crt_at_quick_exit, because
   // we can't unregister it when the DLL is unloaded. This matches how
   // at_quick_exit/quick_exit work with MSVC with a dynamically linked CRT.
   if (__mingw_module_is_dll)
     return 0;
   return _crt_at_quick_exit(func);
+#endif  /* __USING_MCFGTHREAD__  */
 }
 
 int __cdecl (*__MINGW_IMP_SYMBOL(at_quick_exit))(void (__cdecl *)(void)) = 
at_quick_exit;
-- 
2.37.3

Attachment: OpenPGP_signature
Description: OpenPGP digital signature

_______________________________________________
Mingw-w64-public mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/mingw-w64-public

Reply via email to