Skip to content

Improvement #5577 : embedded: after fb_shutdown some files stay locked [CORE5299] #7702

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
179 changes: 100 additions & 79 deletions src/common/unicode_util.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ struct BaseICU

ModuleLoader::Module* formatAndLoad(const char* templateName);
void initialize(ModuleLoader::Module* module);
void finalize(ModuleLoader::Module* module);

template <typename T> string getEntryPoint(const char* name, ModuleLoader::Module* module, T& ptr,
bool optional = false)
Expand Down Expand Up @@ -282,6 +283,15 @@ void BaseICU::initialize(ModuleLoader::Module* module)
}
}

void BaseICU::finalize(ModuleLoader::Module* module)
{
void (U_EXPORT2 *uCleanup)();

getEntryPoint("u_cleanup", module, uCleanup, true);
if (uCleanup)
uCleanup();
}

}

namespace Jrd {
Expand Down Expand Up @@ -477,14 +487,17 @@ class ImplementConversionICU : public UnicodeUtil::ConversionICU, BaseICU
return o;
}

void fini()
{
if (module)
finalize(module);
}

private:
AutoPtr<ModuleLoader::Module> module;
AutoPtr<ModuleLoader::Module> inModule;
};

static ImplementConversionICU* convIcu = NULL;
static GlobalPtr<Mutex> convIcuMutex;


// cache ICU module instances to not load and unload many times
class UnicodeUtil::ICUModules
Expand Down Expand Up @@ -1281,102 +1294,110 @@ void UnicodeUtil::getICUVersion(ICU* icu, int& majorVersion, int& minorVersion)
}


UnicodeUtil::ConversionICU& UnicodeUtil::getConversionICU()
{
if (convIcu)
{
return *convIcu;
}

MutexLockGuard g(convIcuMutex, "UnicodeUtil::getConversionICU");

if (convIcu)
class ConvICUAllocator
{
public:
static Jrd::ImplementConversionICU* create()
{
return *convIcu;
}
Jrd::ImplementConversionICU* convIcu = nullptr;

// Try "favorite" (distributed on windows) version first
const int favMaj = 63;
const int favMin = 1;
try
{
if ((convIcu = ImplementConversionICU::create(favMaj, favMin)))
return *convIcu;
}
catch (const Exception&)
{ }
// Try "favorite" (distributed on windows) version first
const int favMaj = 63;
const int favMin = 1;
try
{
if ((convIcu = Jrd::ImplementConversionICU::create(favMaj, favMin)))
return convIcu;
}
catch (const Exception&)
{ }

// Try system-wide version
try
{
if ((convIcu = ImplementConversionICU::create(0, 0)))
return *convIcu;
}
catch (const Exception&)
{ }

// Do a regular search
LocalStatus ls;
CheckStatusWrapper lastError(&ls);
string version;

// According to http://userguide.icu-project.org/design#TOC-Version-Numbers-in-ICU
// we using two ranges of version numbers: 3.0 - 4.8 and 49 - 79.
// Note 1: the most current version for now is 64, thus it is seems as enough to
// limit upper bound by value of 79. It should be enlarged when necessary in the
// future.
// Note 2: the required function ucal_getTZDataVersion() is available since 3.8.

for (int major = 79; major >= 3;)
{
// Try system-wide version
try
{
if ((convIcu = Jrd::ImplementConversionICU::create(0, 0)))
return convIcu;
}
catch (const Exception&)
{ }

// Do a regular search
LocalStatus ls;
CheckStatusWrapper lastError(&ls);
string version;

// According to http://userguide.icu-project.org/design#TOC-Version-Numbers-in-ICU
// we using two ranges of version numbers: 3.0 - 4.8 and 49 - 79.
// Note 1: the most current version for now is 64, thus it is seems as enough to
// limit upper bound by value of 79. It should be enlarged when necessary in the
// future.
// Note 2: the required function ucal_getTZDataVersion() is available since 3.8.

for (int major = 79; major >= 3;)
{
#ifdef WIN_NT
int minor = 0;
int minor = 0;
#else
int minor = 9;
int minor = 9;
#endif

if (major == 4)
minor = 8;
else if (major <= 4)
minor = 9;
if (major == 4)
minor = 8;
else if (major <= 4)
minor = 9;

for (; minor >= 0; --minor)
{
if ((major == favMaj) && (minor == favMin))
for (; minor >= 0; --minor)
{
continue;
}
if ((major == favMaj) && (minor == favMin))
{
continue;
}

try
{
if ((convIcu = ImplementConversionICU::create(major, minor)))
return *convIcu;
}
catch (const Exception& ex)
{
ex.stuffException(&lastError);
version.printf("Error loading ICU library version %d.%d", major, minor);
try
{
if ((convIcu = Jrd::ImplementConversionICU::create(major, minor)))
return convIcu;
}
catch (const Exception& ex)
{
ex.stuffException(&lastError);
version.printf("Error loading ICU library version %d.%d", major, minor);
}
}

if (major == 49)
major = 4;
else
major--;
}

if (major == 49)
major = 4;
else
major--;
}
Arg::Gds err(isc_icu_library);

Arg::Gds err(isc_icu_library);
if (lastError.getState() & Firebird::IStatus::STATE_ERRORS)
{
err << Arg::StatusVector(lastError.getErrors()) <<
Arg::Gds(isc_random) << Arg::Str(version);
}

if (lastError.getState() & Firebird::IStatus::STATE_ERRORS)
err.raise();
}

static void destroy(Jrd::ImplementConversionICU* inst)
{
err << Arg::StatusVector(lastError.getErrors()) <<
Arg::Gds(isc_random) << Arg::Str(version);
if (inst)
{
inst->fini();
delete inst;
}
}
};

err.raise();
static InitInstance<ImplementConversionICU, ConvICUAllocator> convIcuInstance;

// compiler warning silencer
return *convIcu;
UnicodeUtil::ConversionICU& UnicodeUtil::getConversionICU()
{
return convIcuInstance();
}


Expand Down
25 changes: 20 additions & 5 deletions src/jrd/fun.epp
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
*/

#include "firebird.h"
#include <atomic>
#include <cmath>
#include <stdlib.h>
#include <stdio.h>
Expand Down Expand Up @@ -78,7 +79,8 @@ using namespace Firebird;

namespace
{
bool volatile initDone = false;
const ModuleLoader::Module* bootModule = reinterpret_cast<ModuleLoader::Module*>(0x1);
std::atomic<const ModuleLoader::Module*> ibUtilModule;

struct IbUtilStartup
{
Expand Down Expand Up @@ -123,7 +125,7 @@ namespace
}

ibUtilUnit(IbUtil::alloc);
initDone = true;
ibUtilModule = module;

return true;
}
Expand All @@ -132,9 +134,12 @@ namespace

void IbUtil::initialize()
{
if (initDone || fb_utils::bootBuild())
if (ibUtilModule)
return;

if (fb_utils::bootBuild())
{
initDone = true;
ibUtilModule = bootModule;
return;
}

Expand Down Expand Up @@ -172,6 +177,16 @@ void IbUtil::initialize()
message[2].c_str(), message[3].c_str());
}

void IbUtil::finalize()
{
const ModuleLoader::Module* module = ibUtilModule.exchange(nullptr);

if (!module || module == bootModule)
return;

delete module;
}

void* IbUtil::alloc(long size)
{
thread_db* tdbb = JRD_get_thread_data();
Expand Down Expand Up @@ -318,7 +333,7 @@ void FUN_evaluate(thread_db* tdbb, const Function* function, const NestValueArra
*
**************************************/
// We may be in danger of AV in UDF if ib_util init failed
if (!initDone)
if (!ibUtilModule)
{
ERR_post(Arg::Gds(isc_random) << "ib_util init failed - UDF usage disabled");
}
Expand Down
1 change: 1 addition & 0 deletions src/jrd/fun_proto.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ class IbUtil
{
public:
static void initialize();
static void finalize();

static void* alloc(long size);
static bool free(void* ptr);
Expand Down
1 change: 1 addition & 0 deletions src/jrd/jrd.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4654,6 +4654,7 @@ void JProvider::shutdown(CheckStatusWrapper* status, unsigned int timeout, const
// PluginManager wants to lock a mutex, which is sometimes already locked in current thread
TraceManager::shutdown();
Mapping::shutdownIpc();
IbUtil::finalize();
}

// Wait for completion of all attacment shutdown threads
Expand Down