crt: test: Add new t_tls_exe_dtor_atexit_order test which verifies order of atexit and __tlregdtor callbacks The __tlregdtor callback must be called before any atexit callback independently of the registration order. Signed-off-by: LIU Hao <lh_mouse@126.com>
diff --git a/mingw-w64-crt/testcases/Makefile.am b/mingw-w64-crt/testcases/Makefile.am index 6cfa3f8..f80fdce 100644 --- a/mingw-w64-crt/testcases/Makefile.am +++ b/mingw-w64-crt/testcases/Makefile.am
@@ -140,6 +140,7 @@ t_tls_dll_native \ t_tls_dll_native_process_detach \ t_tls_exe_dtor \ + t_tls_exe_dtor_atexit_order \ t_tls_exe_dyn \ t_tls_exe_native \ t_tls_exe_native_process_detach \
diff --git a/mingw-w64-crt/testcases/t_tls_exe_dtor_atexit_order.c b/mingw-w64-crt/testcases/t_tls_exe_dtor_atexit_order.c new file mode 100644 index 0000000..6554ae3 --- /dev/null +++ b/mingw-w64-crt/testcases/t_tls_exe_dtor_atexit_order.c
@@ -0,0 +1,65 @@ +#include <stdio.h> +#include <stdlib.h> + +#ifndef WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN +#endif +#include <windows.h> + +/* mingw-w64 headers */ +#include "libtest.h" + +extern int __cdecl __tlregdtor(void (__cdecl*func)(void)); + +static int main_success = 0; + +static void __cdecl atexit1_callback(void) +{ + printf("Error: atexit1 calllback was called before __tlregdtor callback\n"); + /* exit, _exit, or ExitProcess calls TLS callbacks, so use TerminateProcess() which is not calling them */ + TerminateProcess(GetCurrentProcess(), 1); +} + +static void __cdecl atexit2_callback(void) +{ + printf("Error: atexit2 calllback was called before __tlregdtor callback\n"); + /* exit, _exit, or ExitProcess calls TLS callbacks, so use TerminateProcess() which is not calling them */ + TerminateProcess(GetCurrentProcess(), 1); +} + +static void __cdecl dtor_callback(void) +{ + printf("SUCCESS: __tlregdtor callback was called\n"); + /* exit, _exit, or ExitProcess calls TLS callbacks, so use TerminateProcess() which is not calling them */ + TerminateProcess(GetCurrentProcess(), main_success ? 0 : 1); +} + +int main(void) +{ + mingw_test_init(); + + /* Register two atexit callbacks, one before __tlregdtor() call and one after __tlregdtor() call. + * The __tlregdtor callback must be called before any atexit callback independently of the registration order. */ + + if (atexit(atexit1_callback) != 0) { + printf("Error: atexit() failed\n"); + /* exit, _exit, or ExitProcess calls TLS callbacks, so use TerminateProcess() which is not calling them */ + TerminateProcess(GetCurrentProcess(), 1); + } + + if (__tlregdtor(&dtor_callback) != 0) { + printf("Error: __tlregdtor() failed\n"); + /* exit, _exit, or ExitProcess calls TLS callbacks, so use TerminateProcess() which is not calling them */ + TerminateProcess(GetCurrentProcess(), 1); + } + + if (atexit(atexit2_callback) != 0) { + printf("Error: atexit() failed\n"); + /* exit, _exit, or ExitProcess calls TLS callbacks, so use TerminateProcess() which is not calling them */ + TerminateProcess(GetCurrentProcess(), 1); + } + + printf("Checking if the __tlregdtor callback would be called before all atexit callbacks...\n"); + main_success = 1; + return 1; /* __tlregdtor callback changes return code to 0 */ +}