From 22c6e0982c91ace544deed86eb8e92358ea29d26 Mon Sep 17 00:00:00 2001 From: shahoian Date: Wed, 8 Dec 2021 21:41:26 +0100 Subject: [PATCH] Do not cleanup cashed CCDB objects of some special types The BasicCCDBManager cache is based on shared_ptr, which assumes that the object is never deleted via its raw pointer. We cannot control this for some global ROOT pointers, e.g. gGeoManager, which is deleted on exit internally by ROOT (thus creating a race condition with destruction of the same pointer via shared_ptr. Such objects will be cached to raw pointers in the BasicCCDBManager but will be never deleted by it. --- CCDB/include/CCDB/BasicCCDBManager.h | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/CCDB/include/CCDB/BasicCCDBManager.h b/CCDB/include/CCDB/BasicCCDBManager.h index aebf96455b412..4e74d9f72c5ee 100644 --- a/CCDB/include/CCDB/BasicCCDBManager.h +++ b/CCDB/include/CCDB/BasicCCDBManager.h @@ -25,6 +25,8 @@ // #include +class TGeoManager; // we need to forward-declare those classes which should not be cleaned up + namespace o2::ccdb { @@ -42,6 +44,7 @@ class CCDBManagerInstance { struct CachedObject { std::shared_ptr objPtr; + void* noCleanupPtr = nullptr; // if assigned instead of objPtr, no cleanup will be done on exit (for global objects cleaned up by the root, e.g. gGeoManager) std::string uuid; long startvalidity = 0; long endvalidity = 0; @@ -53,7 +56,6 @@ class CCDBManagerInstance { mCCDBAccessor.init(path); } - /// set a URL to query from void setURL(const std::string& url); @@ -160,21 +162,25 @@ T* CCDBManagerInstance::getForTimeStamp(std::string const& path, long timestamp) } auto& cached = mCache[path]; if (mCheckObjValidityEnabled && cached.isValid(timestamp)) { - return reinterpret_cast(cached.objPtr.get()); + return reinterpret_cast(cached.noCleanupPtr ? cached.noCleanupPtr : cached.objPtr.get()); } T* ptr = mCCDBAccessor.retrieveFromTFileAny(path, mMetaData, timestamp, &mHeaders, cached.uuid, mCreatedNotAfter ? std::to_string(mCreatedNotAfter) : "", mCreatedNotBefore ? std::to_string(mCreatedNotBefore) : ""); if (ptr) { // new object was shipped, old one (if any) is not valid anymore - cached.objPtr.reset(ptr); + if constexpr (std::is_same::value) { // some special objects cannot be cached to shared_ptr since root may delete their raw global pointer + cached.noCleanupPtr = ptr; + } else { + cached.objPtr.reset(ptr); + } cached.uuid = mHeaders["ETag"]; cached.startvalidity = std::stol(mHeaders["Valid-From"]); cached.endvalidity = std::stol(mHeaders["Valid-Until"]); } else if (mHeaders.count("Error")) { // in case of errors the pointer is 0 and headers["Error"] should be set clearCache(path); // in case of any error clear cache for this object } else { // the old object is valid - ptr = reinterpret_cast(cached.objPtr.get()); + ptr = reinterpret_cast(cached.noCleanupPtr ? cached.noCleanupPtr : cached.objPtr.get()); } mHeaders.clear(); mMetaData.clear();