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