From 2c0fd86dafd1f45102034f9a9975f435d92d11a7 Mon Sep 17 00:00:00 2001 From: Freddie Akeroyd <freddie.akeroyd@stfc.ac.uk> Date: Thu, 28 Feb 2008 14:08:23 +0000 Subject: [PATCH] The C atexit() function seems to have a bug and not always destroy singletons in the correct order. Fix involves implementing our own atexit() handler for singletons. Refs #96. --- Code/Mantid/API/src/AlgorithmFactory.cpp | 2 + Code/Mantid/API/src/AlgorithmManager.cpp | 4 +- Code/Mantid/API/src/AnalysisDataService.cpp | 3 +- Code/Mantid/API/src/FrameworkManager.cpp | 3 +- .../Kernel/inc/MantidKernel/SingletonHolder.h | 8 +++- Code/Mantid/Kernel/src/LibraryManager.cpp | 2 + Code/Mantid/Kernel/src/SingletonHolder.cpp | 42 +++++++++++++++++++ 7 files changed, 59 insertions(+), 5 deletions(-) create mode 100644 Code/Mantid/Kernel/src/SingletonHolder.cpp diff --git a/Code/Mantid/API/src/AlgorithmFactory.cpp b/Code/Mantid/API/src/AlgorithmFactory.cpp index 384676c2aa2..9c6a8eba364 100644 --- a/Code/Mantid/API/src/AlgorithmFactory.cpp +++ b/Code/Mantid/API/src/AlgorithmFactory.cpp @@ -13,11 +13,13 @@ namespace API // are constructed so that it is destroyed after us and thus does // not close any loaded DLLs with loaded algorithms in them Mantid::Kernel::LibraryManager::Instance(); + std::cerr << "Algorithm Factory created." << std::endl; g_log.debug() << "Algorithm Factory created." << std::endl; } AlgorithmFactoryImpl::~AlgorithmFactoryImpl() { + std::cerr << "Algorithm Factory destroyed." << std::endl; // g_log.debug() << "Algorithm Factory destroyed." << std::endl; } diff --git a/Code/Mantid/API/src/AlgorithmManager.cpp b/Code/Mantid/API/src/AlgorithmManager.cpp index 63809098247..1c03c714ae5 100644 --- a/Code/Mantid/API/src/AlgorithmManager.cpp +++ b/Code/Mantid/API/src/AlgorithmManager.cpp @@ -16,6 +16,7 @@ namespace Mantid /// Private Constructor for singleton class AlgorithmManagerImpl::AlgorithmManagerImpl(): g_log(Kernel::Logger::get("AlgorithmManager")), no_of_alg(0) { + std::cerr << "Algorithm Manager created." << std::endl; g_log.debug() << "Algorithm Manager created." << std::endl; } @@ -25,7 +26,8 @@ namespace Mantid */ AlgorithmManagerImpl::~AlgorithmManagerImpl() { - g_log.debug() << "Algorithm Manager destroyed." << std::endl; + std::cerr << "Algorithm Manager destroyed." << std::endl; +// g_log.debug() << "Algorithm Manager destroyed." << std::endl; } /** Creates an instance of an algorithm, but does not own that instance diff --git a/Code/Mantid/API/src/AnalysisDataService.cpp b/Code/Mantid/API/src/AnalysisDataService.cpp index 1f27a1d7002..c83bf257e4b 100644 --- a/Code/Mantid/API/src/AnalysisDataService.cpp +++ b/Code/Mantid/API/src/AnalysisDataService.cpp @@ -145,7 +145,8 @@ AnalysisDataServiceImpl::AnalysisDataServiceImpl(const AnalysisDataServiceImpl&) */ AnalysisDataServiceImpl::~AnalysisDataServiceImpl() { - g_log.debug() << "Analysis Data Service destroyed." << std::endl; + std::cerr << "Analysis Data Service destroyed." << std::endl; +// g_log.debug() << "Analysis Data Service destroyed." << std::endl; } diff --git a/Code/Mantid/API/src/FrameworkManager.cpp b/Code/Mantid/API/src/FrameworkManager.cpp index 063b5433df1..741d17b94d5 100644 --- a/Code/Mantid/API/src/FrameworkManager.cpp +++ b/Code/Mantid/API/src/FrameworkManager.cpp @@ -25,14 +25,13 @@ namespace API /// Default constructor FrameworkManagerImpl::FrameworkManagerImpl() : g_log(Kernel::Logger::get("FrameworkManager")) { - std::cout << "FrmMgr created!" << std::endl; g_log.debug() << "FrameworkManager created." << std::endl; } /// Destructor FrameworkManagerImpl::~FrameworkManagerImpl() { - std::cout << "FrmMgr destroyed!" << std::endl; + std::cerr << "FrameworkManager destroyed." << std::endl; // g_log.debug() << "FrameworkManager destroyed." << std::endl; } diff --git a/Code/Mantid/Kernel/inc/MantidKernel/SingletonHolder.h b/Code/Mantid/Kernel/inc/MantidKernel/SingletonHolder.h index c51689cd37b..46cbf5448f1 100644 --- a/Code/Mantid/Kernel/inc/MantidKernel/SingletonHolder.h +++ b/Code/Mantid/Kernel/inc/MantidKernel/SingletonHolder.h @@ -33,6 +33,11 @@ namespace Mantid namespace Kernel { +/// prototype for function passed to atexit() +typedef void (*atexit_func_t)(void); +extern void CleanupSingletons(void); +extern void AddSingleton(atexit_func_t func); + template <typename T> class SingletonHolder { @@ -68,7 +73,8 @@ inline T& SingletonHolder<T>::Instance() { // std::cerr << "creating singleton " << typeid(T).name() << std::endl; pInstance = CreateUsingNew<T>::Create(); - atexit(&DestroySingleton); + AddSingleton(&DestroySingleton); + atexit(&CleanupSingletons); } return *pInstance; } diff --git a/Code/Mantid/Kernel/src/LibraryManager.cpp b/Code/Mantid/Kernel/src/LibraryManager.cpp index be31417fc18..03647a4da0c 100644 --- a/Code/Mantid/Kernel/src/LibraryManager.cpp +++ b/Code/Mantid/Kernel/src/LibraryManager.cpp @@ -20,12 +20,14 @@ namespace Kernel /// Constructor LibraryManagerImpl::LibraryManagerImpl() : g_log(Logger::get("LibraryManager")) { + std::cerr << "LibraryManager created." << std::endl; g_log.debug() << "LibraryManager created." << std::endl; } /// Destructor LibraryManagerImpl::~LibraryManagerImpl() { + std::cerr << "LibraryManager destroyed." << std::endl; // g_log.debug() << "LibraryManager destroyed." << std::endl; } diff --git a/Code/Mantid/Kernel/src/SingletonHolder.cpp b/Code/Mantid/Kernel/src/SingletonHolder.cpp new file mode 100644 index 00000000000..f1c76ae4033 --- /dev/null +++ b/Code/Mantid/Kernel/src/SingletonHolder.cpp @@ -0,0 +1,42 @@ +#include <list> +#include <MantidKernel/SingletonHolder.h> + +namespace Mantid +{ +namespace Kernel +{ + +/// List of functions to call on program exit +static std::list<atexit_func_t>* cleanup_list = NULL; + +/// Function registed to atexit() that will clean up +/// all our singletons +/// This function may be registed more than once, so needs to +/// clear the list once it has called all the functions +void CleanupSingletons(void) +{ + if (cleanup_list == NULL) + { + return; + } + std::list<atexit_func_t>::const_iterator it; + for(it=cleanup_list->begin(); it != cleanup_list->end(); it++) + { + (*(*it))(); + } + delete cleanup_list; + cleanup_list = NULL; +} + +/// Add s singleton cleanup function to our atexit list +void AddSingleton(atexit_func_t func) +{ + if (cleanup_list == NULL) + { + cleanup_list = new std::list<atexit_func_t>; + } + cleanup_list->push_front(func); +} + +} +} -- GitLab