ReactOS 0.4.16-dev-747-gbc52d5f
exit.cpp
Go to the documentation of this file.
1//
2// exit.cpp
3//
4// Copyright (c) Microsoft Corporation. All rights reserved.
5//
6// The exit() implementation
7//
8#include <corecrt_internal.h>
9#include <eh.h>
10#include <process.h>
11
13
16
17// thread_local atexit dtor handling. The APPCRT exports a function to set the
18// callback function. The exe main function will call this to set the callback
19// function so exit() can invoke destructors for thread-storage objects owned
20// by the main thread.
21static _tls_callback_type thread_local_exit_callback_func;
22
23
24// CRT_REFACTOR TODO This needs to be declared somewhere more accessible and we
25// need to clean up the static CRT exit coordination.
26#if !defined CRTDLL && defined _DEBUG
27 extern "C" bool __cdecl __scrt_uninitialize_crt(bool is_terminating, bool from_exit);
28#endif
29
30
31// Enclaves have no support for managed apps
32#ifdef _UCRT_ENCLAVE_BUILD
33
34static bool __cdecl is_managed_app() throw() { return false; }
35
36static void __cdecl try_cor_exit_process(UINT const) throw() { }
37
38// This function never returns. It causes the process to exit.
39static void __cdecl exit_or_terminate_process(UINT const return_code) throw()
40{
41 TerminateProcess(GetCurrentProcess(), return_code);
42}
43
44#else /* ^^^ _UCRT_ENCLAVE_BUILD ^^^ // vvv !_UCRT_ENCLAVE_BUILD vvv */
45
47
48// CRT_REFACTOR TODO This is duplicated in the VCStartup utility_desktop.cpp.
50{
51 PIMAGE_DOS_HEADER const dos_header = reinterpret_cast<PIMAGE_DOS_HEADER>(GetModuleHandleW(nullptr));
52 if (dos_header == nullptr)
53 return false;
54
56 return false;
57
58 PIMAGE_NT_HEADERS const pe_header = reinterpret_cast<PIMAGE_NT_HEADERS>(
59 reinterpret_cast<BYTE*>(dos_header) + dos_header->e_lfanew);
60
61 if (pe_header->Signature != IMAGE_NT_SIGNATURE)
62 return false;
63
65 return false;
66
67 // prefast assumes we are overrunning __ImageBase
68 #pragma warning(push)
69 #pragma warning(disable: 26000)
70
72 return false;
73
74 #pragma warning(pop)
75
77 return false;
78
79 return true;
80}
81
82static void __cdecl try_cor_exit_process(UINT const return_code) throw()
83{
84 __crt_unique_hmodule mscoree;
85 if (!GetModuleHandleExW(0, L"mscoree.dll", mscoree.get_address_of()))
86 return;
87
88 auto const cor_exit_process = __crt_get_proc_address<exit_process_pft>(mscoree.get(), "CorExitProcess");
89 if (!cor_exit_process)
90 return;
91
92 cor_exit_process(return_code);
93}
94
95
96
97// For Windows Store apps, starting in Windows 10, we use TerminateProcess
98// instead of ExitProcess. ExitProcess will allow threads to run during
99// termination in an unordered fashion. This has lead to problems in various
100// apps. TerminateProcess does not allow threads to run while the process is
101// being torn down. See also CoreApplication::Run, which does the same.
102//
103// For non-Windows Store app processes, we continue to call ExitProcess, for
104// compatibility with the legacy runtimes.
106{
108 {
109 return false;
110 }
111
112 // If application verifier is running, we still want to call ExitProcess,
113 // to enable tools that require DLLs to be unloaded cleanly at process exit
114 // to do their work.
116 {
117 return false;
118 }
119
120 return true;
121}
122
123
124
125// This function never returns. It causes the process to exit.
126static void __cdecl exit_or_terminate_process(UINT const return_code) throw()
127{
129 {
130 TerminateProcess(GetCurrentProcess(), return_code);
131 }
132
133 try_cor_exit_process(return_code);
134
135 // If that returned, then the exe for this process is not managed or we
136 // failed to exit via a call to CorExitProcess. Exit the normal way:
137 ExitProcess(return_code);
138}
139
140#endif /* _UCRT_ENCLAVE_BUILD */
141
142
143static int __cdecl atexit_exception_filter(unsigned long const _exception_code) throw()
144{
145 if (_exception_code == ('msc' | 0xE0000000))
146 {
148 }
149
151}
152
153
154
155extern "C" void __cdecl __acrt_initialize_thread_local_exit_callback(void * encoded_null)
156{
157 thread_local_exit_callback_func = reinterpret_cast<_tls_callback_type>(encoded_null);
158}
159
160// Register the dynamic TLS dtor callback. Called from the vcstartup library
161// as part of the EXE common_main to allow the acrt to call back into the scrt.
162extern "C" void __cdecl _register_thread_local_exe_atexit_callback(_In_ _tls_callback_type const _Callback)
163{
164 // Can only set the callback once.
165 if (thread_local_exit_callback_func != __crt_fast_encode_pointer(nullptr))
166 {
167 terminate();
168 }
169
170 thread_local_exit_callback_func = __crt_fast_encode_pointer(_Callback);
171}
172
173
174
176 int const return_code,
177 _crt_exit_cleanup_mode const cleanup_mode,
178 _crt_exit_return_mode const return_mode
179 ) throw()
180{
181 // First, check to see if we're loaded in a managed app. If we are, try to
182 // call CorExitProcess to let the CLR handle the process termination. If
183 // the call to CorExitProcess is successful, then it will call back through
184 // this function with a return mode of _crt_exit_return_to_caller, at which
185 // point we will run the C termination routines. It will then terminate the
186 // process itself and not return.
187 if (return_mode == _crt_exit_terminate_process && is_managed_app())
188 {
189 try_cor_exit_process(return_code);
190 }
191
192 // Run the C termination:
193 bool crt_uninitialization_required = false;
194
195 __acrt_lock_and_call(__acrt_select_exit_lock(), [&]
196 {
197 static bool c_exit_complete = false;
198 if (c_exit_complete)
199 {
200 return;
201 }
202
204
205 __try
206 {
207 if (cleanup_mode == _crt_exit_full_cleanup)
208 {
209
210 // If this module has any dynamically initialized
211 // __declspec(thread) variables, then we invoke their
212 // destruction for the primary thread. All thread_local
213 // destructors are sequenced before any atexit calls or static
214 // object destructors (3.6.3/1)
215 if (thread_local_exit_callback_func != __crt_fast_encode_pointer(nullptr))
216 {
217 (__crt_fast_decode_pointer(thread_local_exit_callback_func))(nullptr, DLL_PROCESS_DETACH, nullptr);
218 }
219
221 }
222 else if (cleanup_mode == _crt_exit_quick_cleanup)
223 {
225 }
226 }
228 {
229 terminate();
230 }
232
233 #ifndef CRTDLL
234 // When the CRT is statically linked, we are responsible for executing
235 // the terminators here, because the CRT code is present in this module.
236 // When the CRT DLLs are used, the terminators will be executed when
237 // the CRT DLLs are unloaded, after the call to ExitProcess.
238 if (cleanup_mode == _crt_exit_full_cleanup)
239 {
241 }
242
244 #endif // CRTDLL
245
246 if (return_mode == _crt_exit_terminate_process)
247 {
248 c_exit_complete = true;
249 crt_uninitialization_required = true;
250 }
251 });
252
253 // Do NOT try to uninitialize the CRT while holding one of its locks.
254 if (crt_uninitialization_required)
255 {
256 // If we are about to terminate the process, if the debug CRT is linked
257 // statically into this module and this module is an EXE, we need to
258 // ensure that we fully and correctly uninitialize the CRT so that the
259 // debug on-exit() checks (e.g. debug heap leak detection) have a chance
260 // to run.
261 //
262 // We do not need to uninitialize the CRT when it is statically linked
263 // into a DLL because its DllMain will be called for DLL_PROCESS_DETACH
264 // and we can uninitialize the CRT there.
265 //
266 // We never need to uninitialize the retail CRT during exit() because
267 // the process is about to terminate.
268 #if !CRTDLL && _DEBUG
269 __scrt_uninitialize_crt(true, true);
270 #endif
271 }
272
273 if (return_mode == _crt_exit_terminate_process)
274 {
275 exit_or_terminate_process(return_code);
276 }
277}
278
280{
281 return static_cast<int>(__crt_interlocked_read(&c_termination_complete));
282}
283
284
285
286extern "C" void __cdecl exit(int const return_code)
287{
290}
291
292extern "C" void __cdecl _exit(int const return_code)
293{
296}
297
298extern "C" void __cdecl _Exit(int const return_code)
299{
302}
303
304extern "C" void __cdecl quick_exit(int const return_code)
305{
308}
309
310extern "C" void __cdecl _cexit()
311{
313}
314
315extern "C" void __cdecl _c_exit()
316{
318}
bool __cdecl __scrt_uninitialize_crt(bool is_terminating, bool from_exit)
#define __cdecl
Definition: accygwin.h:79
process_end_policy __cdecl __acrt_get_process_end_policy(void)
bool __cdecl __acrt_app_verifier_enabled(void)
Definition: peb_access.cpp:14
@ process_end_policy_exit_process
#define __acrt_select_exit_lock()
_ACRTIMP int __cdecl _execute_onexit_table(_In_opt_ _onexit_table_t *_Table)
_ACRTIMP void __cdecl _initterm(_In_reads_(_Last - _First) _In_ _PVFV *_First, _In_ _PVFV *_Last)
result_buffer_count char *const _In_ int const _In_ bool const _In_ unsigned const _In_ STRFLT const _In_ bool const _Inout_ __crt_cached_ptd_host &ptd throw()
Definition: cvt.cpp:119
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define DLL_PROCESS_DETACH
Definition: compat.h:130
#define GetCurrentProcess()
Definition: compat.h:759
BOOL WINAPI GetModuleHandleExW(IN DWORD dwFlags, IN LPCWSTR lpwModuleName OPTIONAL, OUT HMODULE *phModule)
Definition: loader.c:866
HMODULE WINAPI GetModuleHandleW(LPCWSTR lpModuleName)
Definition: loader.c:838
VOID WINAPI ExitProcess(IN UINT uExitCode)
Definition: proc.c:1487
BOOL WINAPI TerminateProcess(IN HANDLE hProcess, IN UINT uExitCode)
Definition: proc.c:1532
void __cdecl _Exit(int const return_code)
Definition: exit.cpp:298
void __cdecl _exit(int const return_code)
Definition: exit.cpp:292
void __cdecl __acrt_initialize_thread_local_exit_callback(void *encoded_null)
Definition: exit.cpp:155
_onexit_table_t __acrt_at_quick_exit_table
Definition: exit.cpp:15
static bool __cdecl is_managed_app()
Definition: exit.cpp:49
int __cdecl _is_c_termination_complete()
Definition: exit.cpp:279
static int __cdecl atexit_exception_filter(unsigned long const _exception_code)
Definition: exit.cpp:143
static void __cdecl common_exit(int const return_code, _crt_exit_cleanup_mode const cleanup_mode, _crt_exit_return_mode const return_mode)
Definition: exit.cpp:175
static void __cdecl exit_or_terminate_process(UINT const return_code)
Definition: exit.cpp:126
static _tls_callback_type thread_local_exit_callback_func
Definition: exit.cpp:21
static bool __cdecl should_call_terminate_process()
Definition: exit.cpp:105
void(WINAPI * exit_process_pft)(UINT)
Definition: exit.cpp:46
void __cdecl _c_exit()
Definition: exit.cpp:315
_onexit_table_t __acrt_atexit_table
Definition: exit.cpp:14
static long c_termination_complete
Definition: exit.cpp:12
void __cdecl _register_thread_local_exe_atexit_callback(_In_ _tls_callback_type const _Callback)
Definition: exit.cpp:162
void __cdecl _cexit()
Definition: exit.cpp:310
static void __cdecl try_cor_exit_process(UINT const return_code)
Definition: exit.cpp:82
void __cdecl quick_exit(int const return_code)
Definition: exit.cpp:304
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:90
#define EXCEPTION_CONTINUE_SEARCH
Definition: excpt.h:91
_PVFV __xp_z[]
_PVFV __xp_a[]
_PVFV __xt_a[]
_PVFV __xt_z[]
long __cdecl _InterlockedExchange(_Interlocked_operand_ long volatile *_Target, long _Value)
void MSVCRT() terminate()
Definition: cpp.c:716
static IMAGE_DOS_HEADER dos_header
Definition: data.c:13
unsigned int UINT
Definition: ndis.h:50
#define _In_
Definition: no_sal2.h:158
#define UNREACHABLE
#define IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR
Definition: ntimage.h:489
#define IMAGE_NT_OPTIONAL_HDR_MAGIC
Definition: ntimage.h:387
#define L(x)
Definition: ntvdm.h:50
#define IMAGE_NT_SIGNATURE
Definition: pedump.c:93
#define IMAGE_DOS_SIGNATURE
Definition: pedump.c:89
#define __try
Definition: pseh2_64.h:172
#define _exception_code()
Definition: pseh2_64.h:178
#define __except
Definition: pseh2_64.h:173
#define __endtry
Definition: pseh2_64.h:175
#define GetExceptionCode()
Definition: exception.h:68
#define exit(n)
Definition: config.h:202
IMAGE_OPTIONAL_HEADER32 OptionalHeader
Definition: ntddk_ex.h:184
IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES]
Definition: ntddk_ex.h:178
_crt_exit_cleanup_mode
@ _crt_exit_full_cleanup
@ _crt_exit_quick_cleanup
@ _crt_exit_no_cleanup
_crt_exit_return_mode
@ _crt_exit_terminate_process
@ _crt_exit_return_to_caller
#define WINAPI
Definition: msvc.h:6
unsigned char BYTE
Definition: xxhash.c:193