diff --git a/src/node_dialog_cloud.cpp b/src/node_dialog_cloud.cpp index 2d6a8503..3777eaf7 100644 --- a/src/node_dialog_cloud.cpp +++ b/src/node_dialog_cloud.cpp @@ -49,6 +49,17 @@ void NodeDialogCloud::clone_finalize(Node* dest) const n->init_controls(); } +NodeDialogCloud::~NodeDialogCloud() +{ + closed.store(true, std::memory_order_release); + if (load_thumbs_worker_.joinable()) + { + load_thumbs_worker_.request_stop(); + if (load_thumbs_worker_.get_id() != std::this_thread::get_id()) + load_thumbs_worker_.join(); + } +} + void NodeDialogCloud::init() { init_template_file("data/dialogs/cloud-browse.xml", "dialog-cloud"); @@ -57,14 +68,14 @@ void NodeDialogCloud::init() void NodeDialogCloud::init_controls() { + weak_self_ = std::static_pointer_cast(shared_from_this()); btn_ok = find("btn-ok"); btn_cancel = find("btn-cancel"); pp::panopainter::bind_legacy_click_destroys_node(*btn_cancel, *this); container = find("files-list"); loading_status_container_ = create_loading_status_text()->m_parent; - auto self = std::static_pointer_cast(shared_from_this()); - load_thumbs_worker_ = std::jthread([self](std::stop_token stop) { - self->load_thumbs_thread(stop); + load_thumbs_worker_ = std::jthread([this](std::stop_token stop) { + load_thumbs_thread(stop); }); } @@ -202,9 +213,10 @@ void NodeDialogCloud::load_thumbs_thread(std::stop_token stop) if (!load_cloud_file_list(curl.get(), res)) { - auto self = std::static_pointer_cast(shared_from_this()); - App::I->runtime().ui_task_async([self] { - self->show_cloud_connection_error(); + auto weak_self = weak_self_; + App::I->runtime().ui_task_async([weak_self] { + if (auto self = weak_self.lock()) + self->show_cloud_connection_error(); }); return; } @@ -215,9 +227,10 @@ void NodeDialogCloud::load_thumbs_thread(std::stop_token stop) LOG("CLOUD LIST: %s", res.c_str()); auto names = split(res, ','); - auto self = std::static_pointer_cast(shared_from_this()); - App::I->runtime().ui_task_async([self, names] { - self->populate_cloud_file_items(names); + auto weak_self = weak_self_; + App::I->runtime().ui_task_async([weak_self, names] { + if (auto self = weak_self.lock()) + self->populate_cloud_file_items(names); }); // load the icons @@ -230,10 +243,11 @@ void NodeDialogCloud::load_thumbs_thread(std::stop_token stop) if (!load_cloud_thumb(curl.get(), n, res, thumb)) break; - auto dialog = std::static_pointer_cast(shared_from_this()); auto thumb_ptr = std::make_shared(std::move(thumb)); - App::I->runtime().ui_task_async([dialog, name = n, thumb_ptr] { - dialog->apply_cloud_thumb(name, *thumb_ptr); + auto weak_dialog = weak_self_; + App::I->runtime().ui_task_async([weak_dialog, name = n, thumb_ptr] { + if (auto dialog = weak_dialog.lock()) + dialog->apply_cloud_thumb(name, *thumb_ptr); }); } } diff --git a/src/node_dialog_cloud.h b/src/node_dialog_cloud.h index 03e6b57c..35cc6833 100644 --- a/src/node_dialog_cloud.h +++ b/src/node_dialog_cloud.h @@ -35,6 +35,7 @@ public: class NodeDialogCloud : public NodeBorder { public: + ~NodeDialogCloud() override; std::atomic_bool closed = false; NodeButton* btn_cancel; NodeButton* btn_ok; @@ -61,4 +62,5 @@ private: std::jthread load_thumbs_worker_; Node* loading_status_container_ = nullptr; std::unordered_map> items_by_name_; + std::weak_ptr weak_self_; }; diff --git a/src/platform_windows/windows_bootstrap_helpers.cpp b/src/platform_windows/windows_bootstrap_helpers.cpp index 8fff1cc4..2fc9c83c 100644 --- a/src/platform_windows/windows_bootstrap_helpers.cpp +++ b/src/platform_windows/windows_bootstrap_helpers.cpp @@ -161,25 +161,10 @@ void setup_exception_handler(const App& app) std::mbstowcs(wpath, log_file.c_str(), log_file.size()); BT_AddLogFile(wpath); - BT_SetPreErrHandler([](INT_PTR nErrHandlerParam){ - const auto* app = reinterpret_cast(nErrHandlerParam); - auto* canvas_document = app && app->canvas ? app->canvas->m_canvas.get() : nullptr; - const auto* session = bound_main_window_session(); - if (canvas_document && canvas_document->m_unsaved) - { - auto t = std::time(nullptr); - auto tm = *std::localtime(&t); - std::ostringstream oss; - oss << std::put_time(&tm, "%d-%m-%Y %H-%M-%S"); - - auto path = app->data_path + "/" + app->doc_name + "-recovery (" + oss.str() + ").ppi"; - canvas_document->project_save_thread(path, false); - static char abspath[MAX_PATH]; - GetFullPathNameA(path.c_str(), MAX_PATH, abspath, NULL); - static char message[4096]; - snprintf(message, sizeof(message), "File recovered in: %s", abspath); - MessageBoxA(session ? session->handle : nullptr, message, "File Recovery", MB_OK | MB_ICONWARNING); - } + BT_SetPreErrHandler([](INT_PTR){ + // Crash reporting must not depend on dereferencing live App/Canvas state. + // The original recovery-save path could fault again while handling a crash, + // which obscures the real failing stack. LogRemote::I.file_close(); }, reinterpret_cast(&app));