diff --git a/modules/core/src/system.cpp b/modules/core/src/system.cpp index 51c7363b30..b6810fa9f5 100644 --- a/modules/core/src/system.cpp +++ b/modules/core/src/system.cpp @@ -1800,12 +1800,31 @@ static TlsStorage &getTlsStorage() #ifndef _WIN32 // pthread key destructor static void opencv_tls_destructor(void* pData) { + if (!g_isTlsStorageInitialized) + return; // nothing to release, so prefer to avoid creation of new global structures getTlsStorage().releaseThread(pData); } #else // _WIN32 #ifdef CV_USE_FLS static void WINAPI opencv_fls_destructor(void* pData) { + // Empiric detection of ExitProcess call + DWORD code = STILL_ACTIVE/*259*/; + BOOL res = GetExitCodeProcess(GetCurrentProcess(), &code); + if (res && code != STILL_ACTIVE) + { + // Looks like we are in ExitProcess() call + // This is FLS specific only because their callback is called before DllMain. + // TLS doesn't have similar problem, DllMain() is called first which mark __termination properly. + // Note: this workaround conflicts with ExitProcess() steps order described in documentation, however it works: + // 3. ... called with DLL_PROCESS_DETACH + // 7. The termination status of the process changes from STILL_ACTIVE to the exit value of the process. + // (ref: https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-exitprocess) + cv::__termination = true; + } + + if (!g_isTlsStorageInitialized) + return; // nothing to release, so prefer to avoid creation of new global structures getTlsStorage().releaseThread(pData); } #endif // CV_USE_FLS