From 7905acf38a8114c13270bed61305851642454e31 Mon Sep 17 00:00:00 2001 From: David Capello Date: Mon, 11 Mar 2024 17:15:13 -0300 Subject: [PATCH] Handle some extra CannotWriteDocException cases when ContextWriter is used (#4367) One fix that this patch includes for #4367 (crash by unhandled CannotWriteDocException exception) is when we drag-and-drop a tag border to resize its limits. This is a fix for that case but we don't know if this include all cases of #4367 crashes (so we cannot close the issue). Anyway we have added some try { } catch in cases where it's better to avoid propagating the exception, e.g. in MovingSelectionState::onLeaveState() to avoid throwing exceptions in Editor::backToPreviousState() which might be problematic in several cases. (Maybe related to #2829?) --- src/app/commands/cmd_mask_by_color.cpp | 20 ++++----- src/app/commands/cmd_options.cpp | 13 ++++-- src/app/commands/cmd_sprite_properties.cpp | 45 ++++++++++++-------- src/app/ui/editor/moving_selection_state.cpp | 8 +++- src/app/ui/input_chain_element.h | 3 ++ src/app/ui/timeline/timeline.cpp | 27 +++++++----- 6 files changed, 72 insertions(+), 44 deletions(-) diff --git a/src/app/commands/cmd_mask_by_color.cpp b/src/app/commands/cmd_mask_by_color.cpp index 18fa656b3..71d6fad04 100644 --- a/src/app/commands/cmd_mask_by_color.cpp +++ b/src/app/commands/cmd_mask_by_color.cpp @@ -1,5 +1,5 @@ // Aseprite -// Copyright (C) 2018-2023 Igara Studio S.A. +// Copyright (C) 2018-2024 Igara Studio S.A. // Copyright (C) 2001-2018 David Capello // // This program is distributed under the terms of @@ -14,11 +14,12 @@ #include "app/color.h" #include "app/color_utils.h" #include "app/commands/command.h" +#include "app/console.h" #include "app/context.h" #include "app/context_access.h" #include "app/doc.h" -#include "app/ini_file.h" #include "app/i18n/strings.h" +#include "app/ini_file.h" #include "app/modules/gui.h" #include "app/tx.h" #include "app/ui/color_bar.h" @@ -260,22 +261,21 @@ void MaskByColorCommand::maskPreview(const ContextReader& reader) reader.sprite(), image, xpos, ypos, m_selMode->selectionMode())); - { - ContextWriter writer(reader); + + ContextWriter writer(reader); #ifdef SHOW_BOUNDARIES_GEN_PERFORMANCE - base::Chrono chrono; + base::Chrono chrono; #endif - writer.document()->generateMaskBoundaries(mask.get()); + writer.document()->generateMaskBoundaries(mask.get()); #ifdef SHOW_BOUNDARIES_GEN_PERFORMANCE - double time = chrono.elapsed(); - m_window->setText("Mask by Color (" + base::convert_to(time) + ")"); + double time = chrono.elapsed(); + m_window->setText("Mask by Color (" + base::convert_to(time) + ")"); #endif - update_screen_for_document(writer.document()); - } + update_screen_for_document(writer.document()); } } diff --git a/src/app/commands/cmd_options.cpp b/src/app/commands/cmd_options.cpp index 19ea43383..63f9d89fa 100644 --- a/src/app/commands/cmd_options.cpp +++ b/src/app/commands/cmd_options.cpp @@ -784,10 +784,15 @@ public: m_context->activeDocument() && m_context->activeDocument()->sprite() && m_context->activeDocument()->sprite()->gridBounds() != gridBounds()) { - ContextWriter writer(m_context); - Tx tx(writer, Strings::commands_GridSettings(), ModifyDocument); - tx(new cmd::SetGridBounds(writer.sprite(), gridBounds())); - tx.commit(); + try { + ContextWriter writer(m_context, 1000); + Tx tx(writer, Strings::commands_GridSettings(), ModifyDocument); + tx(new cmd::SetGridBounds(writer.sprite(), gridBounds())); + tx.commit(); + } + catch (const std::exception& ex) { + Console::showException(ex); + } } m_curPref->show.grid(gridVisible()->isSelected()); diff --git a/src/app/commands/cmd_sprite_properties.cpp b/src/app/commands/cmd_sprite_properties.cpp index 14327fb98..a601b6fb4 100644 --- a/src/app/commands/cmd_sprite_properties.cpp +++ b/src/app/commands/cmd_sprite_properties.cpp @@ -1,5 +1,5 @@ // Aseprite -// Copyright (C) 2018-2023 Igara Studio S.A. +// Copyright (C) 2018-2024 Igara Studio S.A. // Copyright (C) 2001-2018 David Capello // // This program is distributed under the terms of @@ -9,31 +9,32 @@ #include "config.h" #endif +#include "app/cmd/add_tileset.h" #include "app/cmd/assign_color_profile.h" #include "app/cmd/convert_color_profile.h" -#include "app/cmd/add_tileset.h" #include "app/cmd/remove_tileset.h" #include "app/cmd/set_pixel_ratio.h" #include "app/cmd/set_user_data.h" #include "app/color.h" #include "app/commands/command.h" +#include "app/console.h" #include "app/context_access.h" #include "app/doc_api.h" #include "app/i18n/strings.h" #include "app/modules/gui.h" #include "app/pref/preferences.h" -#include "app/util/tileset_utils.h" #include "app/tx.h" #include "app/ui/color_button.h" -#include "app/ui/user_data_view.h" #include "app/ui/skin/skin_theme.h" +#include "app/ui/user_data_view.h" #include "app/util/pixel_ratio.h" +#include "app/util/tileset_utils.h" #include "base/mem_utils.h" #include "doc/image.h" #include "doc/palette.h" #include "doc/sprite.h" -#include "doc/user_data.h" #include "doc/tilesets.h" +#include "doc/user_data.h" #include "fmt/format.h" #include "os/color_space.h" #include "os/system.h" @@ -351,12 +352,17 @@ void SpritePropertiesCommand::onExecute(Context* context) [&](){ selectedColorProfile = window.colorProfile()->getSelectedItemIndex(); - ContextWriter writer(context); - Sprite* sprite(writer.sprite()); - Tx tx(writer, Strings::sprite_properties_assign_color_profile()); - tx(new cmd::AssignColorProfile( - sprite, colorSpaces[selectedColorProfile]->gfxColorSpace())); - tx.commit(); + try { + ContextWriter writer(context); + Sprite* sprite(writer.sprite()); + Tx tx(writer, Strings::sprite_properties_assign_color_profile()); + tx(new cmd::AssignColorProfile( + sprite, colorSpaces[selectedColorProfile]->gfxColorSpace())); + tx.commit(); + } + catch (const base::Exception& e) { + Console::showException(e); + } updateButtons(); }); @@ -364,12 +370,17 @@ void SpritePropertiesCommand::onExecute(Context* context) [&](){ selectedColorProfile = window.colorProfile()->getSelectedItemIndex(); - ContextWriter writer(context); - Sprite* sprite(writer.sprite()); - Tx tx(writer, Strings::sprite_properties_convert_color_profile()); - tx(new cmd::ConvertColorProfile( - sprite, colorSpaces[selectedColorProfile]->gfxColorSpace())); - tx.commit(); + try { + ContextWriter writer(context); + Sprite* sprite(writer.sprite()); + Tx tx(writer, Strings::sprite_properties_convert_color_profile()); + tx(new cmd::ConvertColorProfile( + sprite, colorSpaces[selectedColorProfile]->gfxColorSpace())); + tx.commit(); + } + catch (const base::Exception& e) { + Console::showException(e); + } updateButtons(); }); diff --git a/src/app/ui/editor/moving_selection_state.cpp b/src/app/ui/editor/moving_selection_state.cpp index 56bc0b77e..ef829a56f 100644 --- a/src/app/ui/editor/moving_selection_state.cpp +++ b/src/app/ui/editor/moving_selection_state.cpp @@ -1,5 +1,5 @@ // Aseprite -// Copyright (C) 2019-2022 Igara Studio S.A. +// Copyright (C) 2019-2024 Igara Studio S.A. // Copyright (C) 2017-2018 David Capello // // This program is distributed under the terms of @@ -14,6 +14,7 @@ #include "app/cmd/set_mask_position.h" #include "app/commands/command.h" #include "app/commands/commands.h" +#include "app/console.h" #include "app/context_access.h" #include "app/tx.h" #include "app/ui/editor/editor.h" @@ -80,12 +81,15 @@ EditorState::LeaveAction MovingSelectionState::onLeaveState(Editor* editor, Edit doc->generateMaskBoundaries(); } else { - { + try { ContextWriter writer(UIContext::instance(), 1000); Tx tx(writer, "Move Selection Edges", DoesntModifyDocument); tx(new cmd::SetMaskPosition(doc, newOrigin)); tx.commit(); } + catch (const base::Exception& e) { + Console::showException(e); + } doc->resetTransformation(); } doc->notifyGeneralUpdate(); diff --git a/src/app/ui/input_chain_element.h b/src/app/ui/input_chain_element.h index 3a96135a5..17df4bec2 100644 --- a/src/app/ui/input_chain_element.h +++ b/src/app/ui/input_chain_element.h @@ -1,4 +1,5 @@ // Aseprite +// Copyright (C) 2024 Igara Studio S.A. // Copyright (C) 2001-2018 David Capello // // This program is distributed under the terms of @@ -29,6 +30,8 @@ namespace app { virtual bool onCanPaste(Context* ctx) = 0; virtual bool onCanClear(Context* ctx) = 0; + // These commands are executed from Context::executeCommand() + // which catch any exception that is thrown. virtual bool onCut(Context* ctx) = 0; virtual bool onCopy(Context* ctx) = 0; virtual bool onPaste(Context* ctx) = 0; diff --git a/src/app/ui/timeline/timeline.cpp b/src/app/ui/timeline/timeline.cpp index bf0b2f98c..b81f8f6da 100644 --- a/src/app/ui/timeline/timeline.cpp +++ b/src/app/ui/timeline/timeline.cpp @@ -1347,7 +1347,7 @@ bool Timeline::onProcessMessage(Message* msg) else if (mouseMsg->left()) { Command* command = Commands::instance() ->byId(CommandId::FrameTagProperties()); - UIContext::instance()->executeCommand(command, params); + m_context->executeCommand(command, params); } } break; @@ -1389,13 +1389,18 @@ bool Timeline::onProcessMessage(Message* msg) if (tag) { if ((m_state == STATE_RESIZING_TAG_LEFT && tag->fromFrame() != m_resizeTagData.from) || (m_state == STATE_RESIZING_TAG_RIGHT && tag->toFrame() != m_resizeTagData.to)) { - ContextWriter writer(UIContext::instance()); - Tx tx(writer, Strings::commands_FrameTagProperties()); - tx(new cmd::SetTagRange( - tag, - (m_state == STATE_RESIZING_TAG_LEFT ? m_resizeTagData.from: tag->fromFrame()), - (m_state == STATE_RESIZING_TAG_RIGHT ? m_resizeTagData.to: tag->toFrame()))); - tx.commit(); + try { + ContextWriter writer(m_context); + Tx tx(writer, Strings::commands_FrameTagProperties()); + tx(new cmd::SetTagRange( + tag, + (m_state == STATE_RESIZING_TAG_LEFT ? m_resizeTagData.from: tag->fromFrame()), + (m_state == STATE_RESIZING_TAG_RIGHT ? m_resizeTagData.to: tag->toFrame()))); + tx.commit(); + } + catch (const base::Exception& e) { + Console::showException(e); + } regenerateRows(); } @@ -1431,7 +1436,7 @@ bool Timeline::onProcessMessage(Message* msg) Command* command = Commands::instance() ->byId(CommandId::LayerProperties()); - UIContext::instance()->executeCommand(command); + m_context->executeCommand(command); return true; } @@ -1441,7 +1446,7 @@ bool Timeline::onProcessMessage(Message* msg) Params params; params.set("frame", "current"); - UIContext::instance()->executeCommand(command, params); + m_context->executeCommand(command, params); return true; } @@ -1449,7 +1454,7 @@ bool Timeline::onProcessMessage(Message* msg) Command* command = Commands::instance() ->byId(CommandId::CelProperties()); - UIContext::instance()->executeCommand(command); + m_context->executeCommand(command); return true; }