From c005dd8360a4579ab53a2e6164c543585c910fce Mon Sep 17 00:00:00 2001 From: Martin Hierholzer <martin.hierholzer@desy.de> Date: Wed, 28 Sep 2022 13:26:45 +0200 Subject: [PATCH] fix shutdown issues when waiting for devices (cf. #10029) --- include/DeviceManager.h | 2 ++ src/Application.cc | 6 ++++++ src/DeviceManager.cc | 22 ++++++++++++++++++++++ 3 files changed, 30 insertions(+) diff --git a/include/DeviceManager.h b/include/DeviceManager.h index 41dc8159..6579360c 100644 --- a/include/DeviceManager.h +++ b/include/DeviceManager.h @@ -130,6 +130,8 @@ namespace ChimeraTK { */ [[nodiscard]] Device& getDevice() { return _device; } + void terminate() override; + protected: /** * Use this function to read the exception version number. It is locking the variable mutex correctly for you. diff --git a/src/Application.cc b/src/Application.cc index 5a43ea59..972a8059 100644 --- a/src/Application.cc +++ b/src/Application.cc @@ -185,6 +185,12 @@ void Application::shutdown() { internalModule->deactivate(); } + // shutdown all DeviceManagers, otherwise application modules might hang if still waiting for initial values from + // devices + for(auto& pair : _deviceManagerMap) { + pair.second->terminate(); + } + // next deactivate the modules, as they have running threads inside as well for(auto& module : getSubmoduleListRecursive()) { module->terminate(); diff --git a/src/DeviceManager.cc b/src/DeviceManager.cc index 8846a098..0f494945 100644 --- a/src/DeviceManager.cc +++ b/src/DeviceManager.cc @@ -398,4 +398,26 @@ namespace ChimeraTK { /*********************************************************************************************************************/ + void DeviceManager::terminate() { + if(moduleThread.joinable()) { + moduleThread.interrupt(); + // try joining the thread + while(!moduleThread.try_join_for(boost::chrono::milliseconds(10))) { + // send boost interrupted exception through the _errorQueue + try { + throw boost::thread_interrupted(); + } + catch(boost::thread_interrupted&) { + _errorQueue.push_exception(std::current_exception()); + } + + // it may not suffice to send the exception once, as the exception might get overwritten in the queue, thus we + // repeat this until the thread was joined. + } + } + assert(!moduleThread.joinable()); + } + + /*********************************************************************************************************************/ + } // namespace ChimeraTK -- GitLab