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?)
This commit is contained in:
David Capello 2024-03-11 17:15:13 -03:00
parent 7f659d2f86
commit 7905acf38a
6 changed files with 72 additions and 44 deletions

View File

@ -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<std::string>(time) + ")");
double time = chrono.elapsed();
m_window->setText("Mask by Color (" + base::convert_to<std::string>(time) + ")");
#endif
update_screen_for_document(writer.document());
}
update_screen_for_document(writer.document());
}
}

View File

@ -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());

View File

@ -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();
});

View File

@ -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();

View File

@ -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;

View File

@ -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;
}