From bd0b61528cc345309c8b8a00672efbeb0f844082 Mon Sep 17 00:00:00 2001 From: Vassil Vassilev Date: Fri, 13 Dec 2019 11:25:46 +0200 Subject: [PATCH] Allow the atexit functions to be called on their own. In environments where cling's teardown should be controlled more carefully, the atexit function handlers should allow to be called separately. This is useful when a handler depends on alive interpreter and cannot be executed while the interpreter is half shut down. This patch should enable TCling's proper shutdown and relax some of the pain in shutting down ROOT in general. --- include/cling/Interpreter/Interpreter.h | 6 ++++++ lib/Interpreter/IncrementalExecutor.cpp | 4 ++-- lib/Interpreter/IncrementalExecutor.h | 16 +++++++++++----- lib/Interpreter/Interpreter.cpp | 5 +++++ 4 files changed, 24 insertions(+), 7 deletions(-) diff --git a/include/cling/Interpreter/Interpreter.h b/include/cling/Interpreter/Interpreter.h index 0c0b7ab9..abaca47c 100644 --- a/include/cling/Interpreter/Interpreter.h +++ b/include/cling/Interpreter/Interpreter.h @@ -804,6 +804,12 @@ namespace cling { /// void AddAtExitFunc(void (*Func) (void*), void* Arg); + ///\brief Run once the list of registered atexit functions. This is useful + /// when an external process wants to control carefully the teardown because + /// the registered atexit functions require alive interpreter service. + /// + void runAtExitFuncs(); + void GenerateAutoloadingMap(llvm::StringRef inFile, llvm::StringRef outFile, bool enableMacros = false, bool enableLogs = true); diff --git a/lib/Interpreter/IncrementalExecutor.cpp b/lib/Interpreter/IncrementalExecutor.cpp index 09c69ac0..43b37154 100644 --- a/lib/Interpreter/IncrementalExecutor.cpp +++ b/lib/Interpreter/IncrementalExecutor.cpp @@ -109,7 +109,7 @@ IncrementalExecutor::IncrementalExecutor(clang::DiagnosticsEngine& diags, // Keep in source: ~unique_ptr needs ClingJIT IncrementalExecutor::~IncrementalExecutor() {} -void IncrementalExecutor::shuttingDown() { +void IncrementalExecutor::runAtExitFuncs() { // It is legal to register an atexit handler from within another atexit // handler and furthor-more the standard says they need to run in reverse // order, so this function must be recursion safe. @@ -126,7 +126,7 @@ void IncrementalExecutor::shuttingDown() { AtExit(); // The standard says that they need to run in reverse order, which means // anything added from 'AtExit()' must now be run! - shuttingDown(); + runAtExitFuncs(); } } diff --git a/lib/Interpreter/IncrementalExecutor.h b/lib/Interpreter/IncrementalExecutor.h index 3122744a..c27ecc4e 100644 --- a/lib/Interpreter/IncrementalExecutor.h +++ b/lib/Interpreter/IncrementalExecutor.h @@ -208,13 +208,19 @@ namespace cling { m_JIT->addModule(module); } - ///\brief Tells the execution context that we are shutting down the system. + ///\brief Tells the execution to run all registered atexit functions once. /// - /// This that notification is needed because the execution context needs to - /// perform extra actions like delete all managed by it symbols, which might - /// still require alive system. + /// This rountine should be used with caution only when an external process + /// wants to carefully control the teardown. For example, if the process + /// has registered its own atexit functions which need the interpreter + /// service to be available when they are being executed. /// - void shuttingDown(); + void runAtExitFuncs(); + + ///\brief A more meaningful synonym of runAtExitFuncs when used in a more + /// standard teardown. + /// + void shuttingDown() { runAtExitFuncs(); } ///\brief Gets the address of an existing global and whether it was JITted. /// diff --git a/lib/Interpreter/Interpreter.cpp b/lib/Interpreter/Interpreter.cpp index dee9f648..28b83fa6 100644 --- a/lib/Interpreter/Interpreter.cpp +++ b/lib/Interpreter/Interpreter.cpp @@ -1718,6 +1718,11 @@ namespace cling { m_Executor->AddAtExitFunc(Func, Arg, getLatestTransaction()->getModule()); } + void Interpreter::runAtExitFuncs() { + assert(!isInSyntaxOnlyMode() && "Must have JIT"); + m_Executor->runAtExitFuncs(); + } + void Interpreter::GenerateAutoloadingMap(llvm::StringRef inFile, llvm::StringRef outFile, bool enableMacros,