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 3032 : int GDALIsInGlobalDestructor() 28 : { 29 3032 : 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 : * This function may be called by application code, since 46 : * it is no longer called automatically, on non-MSVC builds, due to ordering 47 : * problems with respect to automatic destruction of global C++ objects. 48 : * 49 : * Note: no GDAL/OGR code should be called after this call! 50 : * 51 : */ 52 : 53 429 : void GDALDestroy(void) 54 : { 55 429 : if (bGDALDestroyAlreadyCalled) 56 0 : return; 57 429 : bGDALDestroyAlreadyCalled = true; 58 : 59 429 : bInGDALGlobalDestructor = true; 60 : 61 : // logging/error handling may call GDALIsInGlobalDestructor() 62 429 : CPLDebug("GDAL", "In GDALDestroy - unloading GDAL shared library."); 63 : 64 429 : GDALDestroyDriverManager(); 65 : 66 429 : OGRCleanupAll(); 67 429 : GDALPythonFinalize(); 68 429 : bInGDALGlobalDestructor = false; 69 : 70 : /* See corresponding bug reports: */ 71 : /* https://trac.osgeo.org/gdal/ticket/6139 */ 72 : /* https://trac.osgeo.org/gdal/ticket/6868 */ 73 : /* Needed in case no driver manager has been instantiated. */ 74 429 : CPLFreeConfig(); 75 429 : CPLFinalizeTLS(); 76 429 : CPLCleanupErrorMutex(); 77 429 : CPLCleanupMasterMutex(); 78 : } 79 : 80 : /************************************************************************/ 81 : /* The library set-up/clean-up routines implemented with */ 82 : /* GNU C/C++ extensions. */ 83 : /* TODO: Is it Linux-only solution or Unix portable? */ 84 : /************************************************************************/ 85 : #ifdef __GNUC__ 86 : 87 : static void GDALInitialize() __attribute__((constructor)); 88 : 89 : /************************************************************************/ 90 : /* Called when GDAL is loaded by loader or by dlopen(), */ 91 : /* and before dlopen() returns. */ 92 : /************************************************************************/ 93 : 94 1593 : static void GDALInitialize() 95 : { 96 : // nothing to do 97 : // CPLDebug("GDAL", "Library loaded"); 98 : #ifdef DEBUG 99 1593 : const char *pszLocale = CPLGetConfigOption("GDAL_LOCALE", nullptr); 100 1593 : if (pszLocale) 101 0 : CPLsetlocale(LC_ALL, pszLocale); 102 : #endif 103 1593 : } 104 : 105 : #endif // __GNUC__ 106 : 107 : /************************************************************************/ 108 : /* The library set-up/clean-up routine implemented as DllMain entry */ 109 : /* point specific for Windows. */ 110 : /************************************************************************/ 111 : #ifdef _MSC_VER 112 : #ifndef CPL_DISABLE_DLL 113 : 114 : #include <windows.h> 115 : 116 : extern "C" int WINAPI DllMain(HINSTANCE /* hInstance */, DWORD dwReason, 117 : LPVOID /* lpReserved */) 118 : { 119 : if (dwReason == DLL_PROCESS_ATTACH) 120 : { 121 : // nothing to do 122 : } 123 : else if (dwReason == DLL_THREAD_ATTACH) 124 : { 125 : // nothing to do 126 : } 127 : else if (dwReason == DLL_THREAD_DETACH) 128 : { 129 : ::CPLCleanupTLS(); 130 : } 131 : else if (dwReason == DLL_PROCESS_DETACH) 132 : { 133 : GDALDestroy(); 134 : } 135 : 136 : return 1; // ignored for all reasons but DLL_PROCESS_ATTACH 137 : } 138 : 139 : #endif // CPL_DISABLE_DLL 140 : #endif // _MSC_VER