Line data Source code
1 : /****************************************************************************** 2 : * 3 : * Project: GDAL Core 4 : * Purpose: The library set-up/clean-up routines. 5 : * Author: Mateusz Loskot <mateusz@loskot.net> 6 : * 7 : ****************************************************************************** 8 : * Copyright (c) 2010, Mateusz Loskot <mateusz@loskot.net> 9 : * Copyright (c) 2013, Even Rouault <even dot rouault at spatialys.com> 10 : * 11 : * SPDX-License-Identifier: MIT 12 : ****************************************************************************/ 13 : 14 : #include "cpl_port.h" 15 : #include "gdal.h" 16 : #include "gdalpython.h" 17 : 18 : #include "cpl_conv.h" 19 : #include "cpl_error.h" 20 : #include "cpl_multiproc.h" 21 : #include "cpl_string.h" 22 : #include "ogr_api.h" 23 : 24 : static bool bInGDALGlobalDestructor = false; 25 : extern "C" int CPL_DLL GDALIsInGlobalDestructor(); 26 : 27 362 : int GDALIsInGlobalDestructor() 28 : { 29 362 : return bInGDALGlobalDestructor; 30 : } 31 : 32 : void CPLFinalizeTLS(); 33 : 34 : static bool bGDALDestroyAlreadyCalled = FALSE; 35 : 36 : /************************************************************************/ 37 : /* GDALDestroy() */ 38 : /************************************************************************/ 39 : 40 : /** Finalize GDAL/OGR library. 41 : * 42 : * This function calls GDALDestroyDriverManager() and OGRCleanupAll() and 43 : * finalize Thread Local Storage variables. 44 : * 45 : * Prior to GDAL 2.4.0, this function should normally be explicitly called by 46 : * application code if GDAL is dynamically linked (but that does not hurt), 47 : * since it was automatically called through 48 : * the unregistration mechanisms of dynamic library loading. 49 : * 50 : * Since GDAL 2.4.0, this function may be called by application code, since 51 : * it is no longer called automatically, on non-MSVC builds, due to ordering 52 : * problems with respect to automatic destruction of global C++ objects. 53 : * 54 : * Note: no GDAL/OGR code should be called after this call! 55 : * 56 : * @since GDAL 2.0 57 : */ 58 : 59 437 : void GDALDestroy(void) 60 : { 61 437 : if (bGDALDestroyAlreadyCalled) 62 0 : return; 63 437 : bGDALDestroyAlreadyCalled = true; 64 : 65 437 : bInGDALGlobalDestructor = true; 66 : 67 : // logging/error handling may call GDALIsInGlobalDestructor() 68 437 : CPLDebug("GDAL", "In GDALDestroy - unloading GDAL shared library."); 69 : 70 437 : GDALDestroyDriverManager(); 71 : 72 437 : OGRCleanupAll(); 73 437 : GDALPythonFinalize(); 74 437 : bInGDALGlobalDestructor = false; 75 : 76 : /* See corresponding bug reports: */ 77 : /* https://trac.osgeo.org/gdal/ticket/6139 */ 78 : /* https://trac.osgeo.org/gdal/ticket/6868 */ 79 : /* Needed in case no driver manager has been instantiated. */ 80 437 : CPLFreeConfig(); 81 437 : CPLFinalizeTLS(); 82 437 : CPLCleanupErrorMutex(); 83 437 : CPLCleanupMasterMutex(); 84 : } 85 : 86 : /************************************************************************/ 87 : /* The library set-up/clean-up routines implemented with */ 88 : /* GNU C/C++ extensions. */ 89 : /* TODO: Is it Linux-only solution or Unix portable? */ 90 : /************************************************************************/ 91 : #ifdef __GNUC__ 92 : 93 : static void GDALInitialize() __attribute__((constructor)); 94 : 95 : /************************************************************************/ 96 : /* Called when GDAL is loaded by loader or by dlopen(), */ 97 : /* and before dlopen() returns. */ 98 : /************************************************************************/ 99 : 100 1315 : static void GDALInitialize() 101 : { 102 : // nothing to do 103 : // CPLDebug("GDAL", "Library loaded"); 104 : #ifdef DEBUG 105 1315 : const char *pszLocale = CPLGetConfigOption("GDAL_LOCALE", nullptr); 106 1315 : if (pszLocale) 107 0 : CPLsetlocale(LC_ALL, pszLocale); 108 : #endif 109 1315 : } 110 : 111 : #endif // __GNUC__ 112 : 113 : /************************************************************************/ 114 : /* The library set-up/clean-up routine implemented as DllMain entry */ 115 : /* point specific for Windows. */ 116 : /************************************************************************/ 117 : #ifdef _MSC_VER 118 : #ifndef CPL_DISABLE_DLL 119 : 120 : #include <windows.h> 121 : 122 : extern "C" int WINAPI DllMain(HINSTANCE /* hInstance */, DWORD dwReason, 123 : LPVOID /* lpReserved */) 124 : { 125 : if (dwReason == DLL_PROCESS_ATTACH) 126 : { 127 : // nothing to do 128 : } 129 : else if (dwReason == DLL_THREAD_ATTACH) 130 : { 131 : // nothing to do 132 : } 133 : else if (dwReason == DLL_THREAD_DETACH) 134 : { 135 : ::CPLCleanupTLS(); 136 : } 137 : else if (dwReason == DLL_PROCESS_DETACH) 138 : { 139 : GDALDestroy(); 140 : } 141 : 142 : return 1; // ignored for all reasons but DLL_PROCESS_ATTACH 143 : } 144 : 145 : #endif // CPL_DISABLE_DLL 146 : #endif // _MSC_VER