From 70f2ee917e1f6b1eba29e0f44885cb2f42fba209 Mon Sep 17 00:00:00 2001 From: Alexander Alekhin Date: Wed, 10 Oct 2018 13:53:46 +0300 Subject: [PATCH 1/2] cmake: add DllMain() into each OpenCV DLL to detect process termination after ExitProcess() call --- cmake/OpenCVModule.cmake | 8 ++++++++ cmake/templates/dllmain.cpp.in | 36 ++++++++++++++++++++++++++++++++++ modules/core/src/precomp.hpp | 5 +++-- 3 files changed, 47 insertions(+), 2 deletions(-) create mode 100644 cmake/templates/dllmain.cpp.in diff --git a/cmake/OpenCVModule.cmake b/cmake/OpenCVModule.cmake index a869de5cc8..c0b189836f 100644 --- a/cmake/OpenCVModule.cmake +++ b/cmake/OpenCVModule.cmake @@ -909,6 +909,13 @@ macro(_ocv_create_module) source_group("Src" FILES "${_VS_VERSION_FILE}") endif() endif() + if(WIN32 AND NOT ("${the_module}" STREQUAL "opencv_core" OR "${the_module}" STREQUAL "opencv_world") + AND (BUILD_SHARED_LIBS AND NOT "x${OPENCV_MODULE_TYPE}" STREQUAL "xSTATIC") + AND NOT OPENCV_SKIP_DLLMAIN_GENERATION + ) + set(_DLLMAIN_FILE "${CMAKE_CURRENT_BINARY_DIR}/${the_module}_main.cpp") + configure_file("${OpenCV_SOURCE_DIR}/cmake/templates/dllmain.cpp.in" "${_DLLMAIN_FILE}" @ONLY) + endif() source_group("Include" FILES "${OPENCV_CONFIG_FILE_INCLUDE_DIR}/cvconfig.h" "${OPENCV_CONFIG_FILE_INCLUDE_DIR}/opencv2/opencv_modules.hpp") source_group("Src" FILES "${${the_module}_pch}") @@ -918,6 +925,7 @@ macro(_ocv_create_module) "${OPENCV_CONFIG_FILE_INCLUDE_DIR}/cvconfig.h" "${OPENCV_CONFIG_FILE_INCLUDE_DIR}/opencv2/opencv_modules.hpp" ${${the_module}_pch} ${_VS_VERSION_FILE} + ${_DLLMAIN_FILE} ) set_target_properties(${the_module} PROPERTIES LABELS "${OPENCV_MODULE_${the_module}_LABEL};Module") set_source_files_properties(${OPENCV_MODULE_${the_module}_HEADERS} ${OPENCV_MODULE_${the_module}_SOURCES} ${${the_module}_pch} diff --git a/cmake/templates/dllmain.cpp.in b/cmake/templates/dllmain.cpp.in new file mode 100644 index 0000000000..6b3005f654 --- /dev/null +++ b/cmake/templates/dllmain.cpp.in @@ -0,0 +1,36 @@ +// This file is part of OpenCV project. +// It is subject to the license terms in the LICENSE file found in the top-level directory +// of this distribution and at http://opencv.org/license.html. + +#ifndef _WIN32 +#error "Build configuration error" +#endif +#ifndef CVAPI_EXPORTS +#error "Build configuration error" +#endif + +#define WIN32_LEAN_AND_MEAN +#include + +#define OPENCV_MODULE_S "@the_module@" + +namespace cv { +extern __declspec(dllimport) bool __termination; // Details: #12750 +} + +extern "C" +BOOL WINAPI DllMain(HINSTANCE, DWORD fdwReason, LPVOID lpReserved); + +extern "C" +BOOL WINAPI DllMain(HINSTANCE, DWORD fdwReason, LPVOID lpReserved) +{ + if (fdwReason == DLL_THREAD_DETACH || fdwReason == DLL_PROCESS_DETACH) + { + if (lpReserved != NULL) // called after ExitProcess() call + { + //printf("OpenCV: terminating: " OPENCV_MODULE_S "\n"); + cv::__termination = true; + } + } + return TRUE; +} diff --git a/modules/core/src/precomp.hpp b/modules/core/src/precomp.hpp index 6349aa2dfd..6b3b23cddb 100644 --- a/modules/core/src/precomp.hpp +++ b/modules/core/src/precomp.hpp @@ -308,8 +308,9 @@ TLSData& getCoreTlsData(); #define CL_RUNTIME_EXPORT #endif -extern bool __termination; // skip some cleanups, because process is terminating - // (for example, if ExitProcess() was already called) +extern CV_EXPORTS +bool __termination; // skip some cleanups, because process is terminating + // (for example, if ExitProcess() was already called) cv::Mutex& getInitializationMutex(); From 11e2a216c513e302e6bc1c475c40b7717fbb8ed0 Mon Sep 17 00:00:00 2001 From: Alexander Alekhin Date: Wed, 10 Oct 2018 18:04:39 +0000 Subject: [PATCH 2/2] ocl(win32): bypass deallocate() during process termination --- modules/core/src/ocl.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/modules/core/src/ocl.cpp b/modules/core/src/ocl.cpp index 0e98c08659..42aaf8da29 100644 --- a/modules/core/src/ocl.cpp +++ b/modules/core/src/ocl.cpp @@ -4779,6 +4779,10 @@ public: void deallocate_(UMatData* u) const { +#ifdef _WIN32 + if (cv::__termination) // process is not in consistent state (after ExitProcess call) and terminating + return; // avoid any OpenCL calls +#endif if(u->tempUMat()) { CV_Assert(u->origdata);