From 84722876012ca310e29b291e10fef9d18ae26cea Mon Sep 17 00:00:00 2001 From: Vojtech Bubnik Date: Tue, 7 Feb 2023 16:17:26 +0100 Subject: [PATCH] Implementing a test whether the current thread is the main (UI) thread and using it on AppConfig::save() to assert if save is called from a worker thread. The old assert was using thread names, which did not always work on Windows. Fixes #7839 #9178 #9370 #9420 --- src/PrusaSlicer.cpp | 2 ++ src/libslic3r/AppConfig.cpp | 8 ++------ src/libslic3r/Thread.cpp | 20 ++++++++++++++++++++ src/libslic3r/Thread.hpp | 7 +++++++ 4 files changed, 31 insertions(+), 6 deletions(-) diff --git a/src/PrusaSlicer.cpp b/src/PrusaSlicer.cpp index 1ee4b0d34..c5bbccb24 100644 --- a/src/PrusaSlicer.cpp +++ b/src/PrusaSlicer.cpp @@ -72,6 +72,8 @@ int CLI::run(int argc, char **argv) { // Mark the main thread for the debugger and for runtime checks. set_current_thread_name("slic3r_main"); + // Save the thread ID of the main thread. + save_main_thread_id(); #ifdef __WXGTK__ // On Linux, wxGTK has no support for Wayland, and the app crashes on diff --git a/src/libslic3r/AppConfig.cpp b/src/libslic3r/AppConfig.cpp index 48f0d3ab2..3c3a4d18d 100644 --- a/src/libslic3r/AppConfig.cpp +++ b/src/libslic3r/AppConfig.cpp @@ -417,12 +417,8 @@ std::string AppConfig::load() void AppConfig::save() { - { - // Returns "undefined" if the thread naming functionality is not supported by the operating system. - std::optional current_thread_name = get_current_thread_name(); - if (current_thread_name && *current_thread_name != "slic3r_main") - throw CriticalException("Calling AppConfig::save() from a worker thread!"); - } + if (! is_main_thread_active()) + throw CriticalException("Calling AppConfig::save() from a worker thread!"); // The config is first written to a file with a PID suffix and then moved // to avoid race conditions with multiple instances of Slic3r diff --git a/src/libslic3r/Thread.cpp b/src/libslic3r/Thread.cpp index 22d4cb419..aa710aaef 100644 --- a/src/libslic3r/Thread.cpp +++ b/src/libslic3r/Thread.cpp @@ -191,6 +191,26 @@ std::optional get_current_thread_name() #endif // _WIN32 +// To be called at the start of the application to save the current thread ID as the main (UI) thread ID. +static boost::thread::id g_main_thread_id; + +void save_main_thread_id() +{ + g_main_thread_id = boost::this_thread::get_id(); +} + +// Retrieve the cached main (UI) thread ID. +boost::thread::id get_main_thread_id() +{ + return g_main_thread_id; +} + +// Checks whether the main (UI) thread is active. +bool is_main_thread_active() +{ + return get_main_thread_id() == boost::this_thread::get_id(); +} + // Spawn (n - 1) worker threads on Intel TBB thread pool and name them by an index and a system thread ID. // Also it sets locale of the worker threads to "C" for the G-code generator to produce "." as a decimal separator. void name_tbb_thread_pool_threads_set_locale() diff --git a/src/libslic3r/Thread.hpp b/src/libslic3r/Thread.hpp index 252116ea7..19ad29801 100644 --- a/src/libslic3r/Thread.hpp +++ b/src/libslic3r/Thread.hpp @@ -29,6 +29,13 @@ inline bool set_thread_name(boost::thread &thread, const std::string &thread_nam bool set_current_thread_name(const char *thread_name); inline bool set_current_thread_name(const std::string &thread_name) { return set_current_thread_name(thread_name.c_str()); } +// To be called at the start of the application to save the current thread ID as the main (UI) thread ID. +void save_main_thread_id(); +// Retrieve the cached main (UI) thread ID. +boost::thread::id get_main_thread_id(); +// Checks whether the main (UI) thread is active. +bool is_main_thread_active(); + // OSX specific: Set Quality of Service to "user initiated", so that the threads will be scheduled to high performance // cores if available. void set_current_thread_qos();