Bug 414672 - Crash in uninitialized transform tool
Summary: Crash in uninitialized transform tool
Status: RESOLVED FIXED
Alias: None
Product: krita
Classification: Applications
Component: Tools/Transform (show other bugs)
Version: git master (please specify the git hash!)
Platform: Other Linux
: NOR crash
Target Milestone: ---
Assignee: Tiar
URL:
Keywords: regression, release_blocker
: 414638 414645 414797 415090 415388 415654 415675 416468 (view as bug list)
Depends on:
Blocks:
 
Reported: 2019-11-30 00:21 UTC by Tiar
Modified: 2020-01-28 09:50 UTC (History)
10 users (show)

See Also:
Latest Commit:
Version Fixed In:


Attachments
gdb backtrace - thread apply all bt (17.69 KB, text/plain)
2019-11-30 00:21 UTC, Tiar
Details
gdb backtrace - thread apply all bt full (40.43 KB, text/plain)
2019-11-30 00:22 UTC, Tiar
Details
gdb backtrace (2) - thread apply all bt (15.19 KB, text/plain)
2019-11-30 02:42 UTC, Tiar
Details
gdb backtrace (2) - thread apply all bt full (33.86 KB, text/plain)
2019-11-30 02:42 UTC, Tiar
Details
gdb backtrace (3) - thread apply all bt (11.63 KB, text/plain)
2019-11-30 21:16 UTC, Tiar
Details
gdb backtrace (3) - thread apply all bt full (20.85 KB, text/plain)
2019-11-30 21:16 UTC, Tiar
Details
Backtrace trying to reproduce, identical to the one from bug 415625 (22.75 KB, text/plain)
2020-01-08 14:03 UTC, Tiar
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Tiar 2019-11-30 00:21:22 UTC
Created attachment 124195 [details]
gdb backtrace - thread apply all bt

SUMMARY
Krita crashes a lot on transform tool.


STEPS TO REPRODUCE
1. Paint something.
2. Select something.
3. Try to transform it. If it doesn't crash the first time, return to 1.

OBSERVED RESULT
Crash.


EXPECTED RESULT
No crash.


ADDITIONAL INFORMATION
It happened three times in like... well, I wanted to say 2h, but Krita says that I only painted for 30 minutes and the rest of it was browsking internet ;) So I guess it's a pretty serious crash.
Possible duplicates: bug 414645, bug 414638 - someone who's fixing it, please check which commit broke it and if this commit went into 4.2.8.
(Since it looks quite plausible that it's the same thing, it's a quite important regression :/ )

RELEVANT THREADS

Thread 2143 (Thread 0x7fff6e064700 (LWP 3415)):
#0  0x00007ffff426b077 in __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:50
#1  0x00007ffff424c535 in __GI_abort () at abort.c:79
#2  0x00007ffff424c40f in __assert_fail_base (fmt=0x7ffff43d8858 "%s%s%s:%u: %s%sAssertion `%s' failed.\n%n", assertion=0x7fffd49a3f25 "this->is_initialized()", file=0x7fffd49a3cd0 "/usr/include/boost/optional/optional.hpp", line=1191, function=0x7fffd49a40a0 <boost::optional<ToolTransformArgs>::get()::__PRETTY_FUNCTION__> "boost::optional<T>::reference_type boost::optional<T>::get() [with T = ToolTransformArgs; boost::optional<T>::reference_type = ToolTransformArgs&]")
    at assert.c:92
#3  0x00007ffff425c142 in __GI___assert_fail (assertion=0x7fffd49a3f25 "this->is_initialized()", file=0x7fffd49a3cd0 "/usr/include/boost/optional/optional.hpp", line=1191, function=0x7fffd49a40a0 <boost::optional<ToolTransformArgs>::get()::__PRETTY_FUNCTION__> "boost::optional<T>::reference_type boost::optional<T>::get() [with T = ToolTransformArgs; boost::optional<T>::reference_type = ToolTransformArgs&]") at assert.c:101
#4  0x00007fffd49858d5 in non-virtual thunk to TransformStrokeStrategy::finishStrokeCallback() () at /usr/include/boost/optional/optional.hpp:1208
#5  0x00007ffff5ea03cc in non-virtual thunk to KisUpdateJobItem::run() () at /home/tymon/devsec/install/lib/x86_64-linux-gnu/libkritaimage.so.19
#6  0x00007ffff4673f71 in  () at /usr/lib/x86_64-linux-gnu/libQt5Core.so.5
#7  0x00007ffff467bc87 in  () at /usr/lib/x86_64-linux-gnu/libQt5Core.so.5
#8  0x00007ffff2077164 in start_thread (arg=<optimized out>) at pthread_create.c:486
#9  0x00007ffff4344def in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:95

Thread 13 (Thread 0x7fffcee50700 (LWP 23605)):
#0  0x00007ffff433e219 in syscall () at ../sysdeps/unix/sysv/linux/x86_64/syscall.S:38
#1  0x00007ffff4670fd0 in  () at /usr/lib/x86_64-linux-gnu/libQt5Core.so.5
#2  0x00007ffff4670e42 in QSemaphore::tryAcquire(int, int) () at /usr/lib/x86_64-linux-gnu/libQt5Core.so.5
#3  0x00007ffff5af6a53 in KisTileDataSwapper::waitForWork() (this=<optimized out>) at /home/tymon/devsec/krita/libs/image/tiles3/swap/kis_tile_data_swapper.cpp:86
#4  0x00007ffff5af6c8a in KisTileDataSwapper::run() (this=0x7ffff5fc1e80 <(anonymous namespace)::Q_QGS_s_instance::innerFunction()::holder+64>) at /home/tymon/devsec/krita/libs/image/tiles3/swap/kis_tile_data_swapper.cpp:92
#5  0x00007ffff467bc87 in  () at /usr/lib/x86_64-linux-gnu/libQt5Core.so.5
#6  0x00007ffff2077164 in start_thread (arg=<optimized out>) at pthread_create.c:486
#7  0x00007ffff4344def in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:95

Thread 1 (Thread 0x7fffeb49f800 (LWP 23525)):
#0  0x00007ffff207d2eb in futex_wait_cancelable (private=<optimized out>, expected=0, futex_word=0x555572f32bd0) at ../sysdeps/unix/sysv/linux/futex-internal.h:88
#1  0x00007ffff207d2eb in __pthread_cond_wait_common (abstime=0x0, mutex=0x555572f32b80, cond=0x555572f32ba8) at pthread_cond_wait.c:502
#2  0x00007ffff207d2eb in __pthread_cond_wait (cond=0x555572f32ba8, mutex=0x555572f32b80) at pthread_cond_wait.c:655
#3  0x00007ffff467c43b in QWaitCondition::wait(QMutex*, unsigned long) () at /usr/lib/x86_64-linux-gnu/libQt5Core.so.5
#4  0x00007ffff4672822 in QThreadPoolPrivate::waitForDone(int) () at /usr/lib/x86_64-linux-gnu/libQt5Core.so.5
#5  0x00007ffff4672ce1 in QThreadPool::waitForDone(int) () at /usr/lib/x86_64-linux-gnu/libQt5Core.so.5
#6  0x00007ffff5c96f0f in KisUpdateScheduler::barrierLock() (this=0x555573088960) at /home/tymon/devsec/krita/libs/image/kis_update_scheduler.cpp:380
#7  0x00007ffff5cb5738 in KisImage::barrierLock(bool) (this=this@entry=0x555572d95840, readOnly=readOnly@entry=false) at /home/tymon/devsec/krita/libs/image/kis_image.cc:679
#8  0x00007ffff6fae198 in PointerPolicyAlwaysPresent<KisSharedPtr<KisImage> >::barrierLock(KisSharedPtr<KisImage>) (image=...) at /home/tymon/devsec/krita/libs/global/kis_shared_ptr.h:179
#9  0x00007ffff6fae198 in KisImageBarrierLockerImpl<PointerPolicyAlwaysPresent<KisSharedPtr<KisImage> > >::KisImageBarrierLockerImpl(KisSharedPtr<KisImage>) (image=..., this=0x7fffffffd428)
    at /home/tymon/devsec/krita/libs/image/kis_image_barrier_locker.h:68
#10 0x00007ffff6fae198 in KisCutCopyActionFactory::run(bool, bool, KisViewManager*) (this=0x7fffffffd4f0, willCut=<optimized out>, makeSharpClip=<optimized out>, view=0x555559f076a0)
    at /home/tymon/devsec/krita/libs/ui/actions/kis_selection_action_factories.cpp:288
#11 0x00007ffff6dc0692 in KisSelectionManager::copy() (this=0x555570a0d330) at /home/tymon/devsec/krita/libs/ui/kis_selection_manager.cc:369
#12 0x00007ffff711c365 in KisSelectionManager::qt_static_metacall(QObject*, QMetaObject::Call, int, void**) (_o=<optimized out>, _c=<optimized out>, _id=<optimized out>, _a=<optimized out>)
    at /home/tymon/devsec/build/libs/ui/kritaui_autogen/EWIEGA46WW/moc_kis_selection_manager.cpp:237
#13 0x00007ffff484d6db in QMetaObject::activate(QObject*, int, int, void**) () at /usr/lib/x86_64-linux-gnu/libQt5Core.so.5
#14 0x00007ffff51dcef2 in QAction::triggered(bool) () at /usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5
#15 0x00007ffff51df500 in QAction::activate(QAction::ActionEvent) () at /usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5
#16 0x00007ffff51dfdb4 in QAction::event(QEvent*) () at /usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5
#17 0x00007ffff51e34a1 in QApplicationPrivate::notify_helper(QObject*, QEvent*) () at /usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5
#18 0x00007ffff51eaae0 in QApplication::notify(QObject*, QEvent*) () at /usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5
#19 0x00007ffff7006ac7 in KisApplication::notify(QObject*, QEvent*) (this=<optimized out>, receiver=0x5555706e11a0, event=0x7fffffffd980) at /home/tymon/devsec/krita/libs/ui/KisApplication.cpp:653
#20 0x00007ffff4824499 in QCoreApplication::notifyInternal2(QObject*, QEvent*) () at /usr/lib/x86_64-linux-gnu/libQt5Core.so.5
---Type <return> to continue, or q <return> to quit---
#21 0x00007ffff4c54233 in QShortcutMap::dispatchEvent(QKeyEvent*) () at /usr/lib/x86_64-linux-gnu/libQt5Gui.so.5
#22 0x00007ffff4c5430b in QShortcutMap::tryShortcut(QKeyEvent*) () at /usr/lib/x86_64-linux-gnu/libQt5Gui.so.5
#23 0x00007ffff4c09866 in QWindowSystemInterface::handleShortcutEvent(QWindow*, unsigned long, int, QFlags<Qt::KeyboardModifier>, unsigned int, unsigned int, unsigned int, QString const&, bool, unsigned short) ()
    at /usr/lib/x86_64-linux-gnu/libQt5Gui.so.5
#24 0x00007ffff4c25cbd in QGuiApplicationPrivate::processKeyEvent(QWindowSystemInterfacePrivate::KeyEvent*) () at /usr/lib/x86_64-linux-gnu/libQt5Gui.so.5
#25 0x00007ffff4c2b415 in QGuiApplicationPrivate::processWindowSystemEvent(QWindowSystemInterfacePrivate::WindowSystemEvent*) () at /usr/lib/x86_64-linux-gnu/libQt5Gui.so.5
#26 0x00007ffff4c05b6b in QWindowSystemInterface::sendWindowSystemEvents(QFlags<QEventLoop::ProcessEventsFlag>) () at /usr/lib/x86_64-linux-gnu/libQt5Gui.so.5
#27 0x00007fffeabb8e5b in  () at /usr/lib/x86_64-linux-gnu/libQt5XcbQpa.so.5
#28 0x00007ffff482316b in QEventLoop::exec(QFlags<QEventLoop::ProcessEventsFlag>) () at /usr/lib/x86_64-linux-gnu/libQt5Core.so.5
#29 0x00007ffff482b2e2 in QCoreApplication::exec() () at /usr/lib/x86_64-linux-gnu/libQt5Core.so.5
#30 0x0000555555e4e4de in main (argc=<optimized out>, argv=0x7fffffffdfe8) at /home/tymon/devsec/krita/krita/main.cc:584
#31 0x00007ffff424e09b in __libc_start_main (main=0x555555e4d0e0 <main>, argc=1, argv=0x7fffffffdfe8, init=<optimized out>, fini=<optimized out>, rtld_fini=<optimized out>, stack_end=0x7fffffffdfd8) at ../csu/libc-start.c:308
#32 0x0000555555e4f83a in _start () at /home/tymon/devsec/krita/krita/main.cc:461



SOFTWARE/OS VERSIONS
Krita

 Version: 4.3.0-prealpha (git 2d4ae8c)
 Languages: pl
 Hidpi: true

Qt

  Version (compiled): 5.11.1
  Version (loaded): 5.11.1

OS Information

  Build ABI: x86_64-little_endian-lp64
  Build CPU: x86_64
  CPU: x86_64
  Kernel Type: linux
  Kernel Version: 5.3.7-050307-generic
  Pretty Productname: Linux Mint 19.2
  Product Type: linuxmint
  Product Version: 19.2


Hardware Information

  GPU Acceleration: auto
  Memory: 15633 Mb
  Number of Cores: 8
  Swap Location: /tmp

Current Settings

	Current Swap Location: /tmp
	Undo Enabled: 1
	Undo Stack Limit: 30
	Use OpenGL: 1
	Use OpenGL Texture Buffer: 1
	Use AMD Vectorization Workaround: 0
	Canvas State: OPENGL_SUCCESS
	Autosave Interval: 180
	Use Backup Files: 1
	Number of Backups Kept: 1
	Backup File Suffix: ~
	Backup Location: Same Folder as the File
	Use Win8 Pointer Input: 0
	Use RightMiddleTabletButton Workaround: 0
	Levels of Detail Enabled: 1
	Use Zip64: 0
Comment 1 Tiar 2019-11-30 00:22:09 UTC
Created attachment 124196 [details]
gdb backtrace - thread apply all bt full
Comment 2 Tiar 2019-11-30 02:42:26 UTC
Created attachment 124199 [details]
gdb backtrace (2) - thread apply all bt

I was painting inside gdb and noticed this backtrace is slightly different (no cut/copy, only TileManager and TransformTool threads)
Comment 3 Tiar 2019-11-30 02:42:46 UTC
Created attachment 124200 [details]
gdb backtrace (2) - thread apply all bt full
Comment 4 Tiar 2019-11-30 19:21:50 UTC
*** Bug 414638 has been marked as a duplicate of this bug. ***
Comment 5 Tiar 2019-11-30 19:22:11 UTC
*** Bug 414645 has been marked as a duplicate of this bug. ***
Comment 6 Tiar 2019-11-30 21:16:35 UTC
Created attachment 124221 [details]
gdb backtrace (3) - thread apply all bt

I've found a good way to reproduce it. It isn't the nicest backtrace like the second one, but it's reproducible at least.

1. Create a new document.
2. Create a new layer.
3. Use Ellipse Tool (I created a perfect circle).
4. Press ctrl+T to get to the Transform Tool.
5. Select Shape Selection Tool (arrow tool).

Note: if you first transform the circle and then select the other tool, it won't happen.
Comment 7 Tiar 2019-11-30 21:16:50 UTC
Created attachment 124222 [details]
gdb backtrace (3) - thread apply all bt full
Comment 8 Tiar 2019-12-01 00:47:57 UTC
The crash was introduced in commit f336923b87. The cause seems to be calling endStroke() in kis_tool_transform twice, and so fast that the second one doesn't know the first one already started.

Assigning to Dmitry since it's a regression and caused by his changes.

Setting to "release_blocker" because we've got two reports on that besides mine in just a few days and there is just no way to work with transform tool now, so I believe it's quite important. I hope it's not an overstepping of my powers or anything ;)
Comment 9 Dan 2019-12-01 15:34:21 UTC
I believe I'm seeing this too. Start with an image, select transform tool, then paste another image into the first and you get a crash. Command line (Linux) output is

krita: /usr/include/boost/optional/optional.hpp:1191: boost::optional<T>::reference_type boost::optional<T>::get() [with T = ToolTransformArgs; boost::optional<T>::reference_type = ToolTransformArgs&]: Assertion `this->is_initialized()' failed.
/home/dan/Applications/startKrita: line 1: 12553 Aborted
Comment 10 Dan 2019-12-01 15:40:09 UTC
OK, I'm getting crashes all over the place with the Transform tool, same error output as reported above. Just selecting a different layer, while the Transform tool is enabled, causes a crash
Comment 11 Tiar 2019-12-03 14:05:22 UTC
*** Bug 414797 has been marked as a duplicate of this bug. ***
Comment 12 Dmitry Kazakov 2019-12-04 17:43:30 UTC
Git commit 2dc2ed5f5a6be2b81aab5001de8389e3f3cbdcac by Dmitry Kazakov.
Committed on 04/12/2019 at 17:41.
Pushed by dkazakov into branch 'master'.

Fix a crash when cancelling Transform Tool action

The crash happens only on systems that have asserts enabled, that
is, don't have NDEBUG defined.

Binding uninitialized '*m_savedTransformArgs' to a cont-reference
generated valid c++ code (a reference initialized with nullptr),
and given that finishStrokeImpl() didn't try to use/dereference
this reference, the code worked fine and didn't crash on systems
without asserts.

But on systems with asserts enabled (non NDEBUG), boost::optional
triggered a sanity check assert for dereferencing nullptr and crashed
the application.

The patch removes entire code for resetting m_savedTransformArgs in
cancelStrokeCallback(). It was actually an artifact of some initial
refactoring.

Thanks Fredrik Hansson for pointing out the problem!
https://invent.kde.org/kde/krita/merge_requests/197

M  +1    -8    plugins/tools/tool_transform2/strokes/transform_stroke_strategy.cpp

https://invent.kde.org/kde/krita/commit/2dc2ed5f5a6be2b81aab5001de8389e3f3cbdcac
Comment 13 Tiar 2019-12-12 14:24:01 UTC
*** Bug 415090 has been marked as a duplicate of this bug. ***
Comment 14 Tiar 2019-12-20 18:21:05 UTC
*** Bug 415388 has been marked as a duplicate of this bug. ***
Comment 15 Tiar 2019-12-29 14:28:48 UTC
*** Bug 415675 has been marked as a duplicate of this bug. ***
Comment 16 Tiar 2019-12-31 13:03:02 UTC
*** Bug 415654 has been marked as a duplicate of this bug. ***
Comment 17 Halla Rempt 2020-01-03 15:37:10 UTC
I'm still getting this all the time.
Comment 18 Halla Rempt 2020-01-07 15:26:46 UTC
Simple create an image, select the move tool, then the transform tool will assert:

krita: /usr/include/boost/optional/optional.hpp:1107: boost::optional<T>::reference_type boost::optional<T>::get() [with T = ToolTransformArgs; boost::optional<T>::reference_type = ToolTransformArgs&]: Assertion `this->is_initialized()' failed.
KCrash: crashing... crashRecursionCounter = 2
KCrash: Application Name = krita path = /home/boud/dev/i-4.2/bin pid = 14253
KCrash: Arguments: /home/boud/dev/i-4.2/bin/krita
Comment 19 Tiar 2020-01-08 14:03:50 UTC
Created attachment 124975 [details]
Backtrace trying to reproduce, identical to the one from bug 415625

I'm on 3f0ff1a86c + a few irrelevant commits. When I try to reproduce according to boud's steps:
- (I first select Move Tool)
- it doesn't assert after changing from Move Tool to Transform Tool
- it does crash when changing from Transform Tool to Freehand Brush Tool... but the crash log seem to be identical with what I would get in bug 415625:

So @boud if you cannot reproduce it now after fixing bug 415625, that might be a reason and this bug should be closed as well?


Thread 31 "Thread (pooled)" received signal SIGABRT, Aborted.
[Switching to Thread 0x7fff97fff700 (LWP 27201)]
__GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:50
50	../sysdeps/unix/sysv/linux/raise.c: No such file or directory.
(gdb) thread apply all bt

Thread 31 (Thread 0x7fff97fff700 (LWP 27201)):
#0  0x00007ffff4262077 in __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:50
#1  0x00007ffff4243535 in __GI_abort () at abort.c:79
#2  0x00007ffff46318d7 in  () at /usr/lib/x86_64-linux-gnu/libQt5Core.so.5
#3  0x00007ffff4630d59 in qt_assert_x(char const*, char const*, char const*, int) () at /usr/lib/x86_64-linux-gnu/libQt5Core.so.5
#4  0x00007ffff5a15528 in KisStroke::addJob(KisStrokeJobData*) (this=<optimized out>, data=<optimized out>) at /home/tymon/devsec/krita/libs/image/kis_stroke.cpp:84
#5  0x00007ffff5c828e2 in KisStrokesQueue::addJob(QWeakPointer<KisStroke>, KisStrokeJobData*) (this=<optimized out>, id=..., data=0x7fffb80017c0) at /home/tymon/devsec/krita/libs/image/kis_strokes_queue.cpp:339
#6  0x00007ffff5c8fbc0 in KisUpdateScheduler::addJob(QWeakPointer<KisStroke>, KisStrokeJobData*) (this=0x5555739a4c80, id=..., data=<optimized out>) at /usr/include/c++/8/bits/atomic_base.h:295
#7  0x00007ffff5cb8e2f in non-virtual thunk to KisImage::addJob(QWeakPointer<KisStroke>, KisStrokeJobData*) () at /usr/include/c++/8/bits/atomic_base.h:295
#8  0x00007ffff5b75bb2 in KisSavedMacroCommand::addCommands(QWeakPointer<KisStroke>, bool) (this=0x555570ba9df0, id=..., undo=<optimized out>) at /usr/include/c++/8/bits/atomic_base.h:295
#9  0x00007ffff5b74802 in KisSavedMacroCommand::performCancel(QWeakPointer<KisStroke>, bool) (this=<optimized out>, id=..., strokeUndo=<optimized out>) at /usr/include/c++/8/bits/atomic_base.h:295
#10 0x00007ffff5c7de85 in KisStrokeStrategyUndoCommandBased::cancelStrokeCallback() (this=0x55555bb90b60) at /usr/include/c++/8/bits/atomic_base.h:295
#11 0x00007fffd495a2a5 in TransformStrokeStrategy::<lambda()>::operator() (__closure=0x7fffb0004c18, __closure=0x7fffb0004c18) at /home/tymon/devsec/krita/plugins/tools/tool_transform2/strokes/transform_stroke_strategy.cpp:686
#12 0x00007fffd495a2a5 in std::_Function_handler<void (), TransformStrokeStrategy::finishStrokeImpl(bool, ToolTransformArgs const&)::{lambda()#1}>::_M_invoke(std::_Any_data const&) (__functor=...)
    at /usr/include/c++/8/bits/std_function.h:297
#13 0x00007ffff5c7e05b in KisStrokeStrategyUndoCommandBased::doStrokeCallback(KisStrokeJobData*) (this=0x55555bb90b60, data=0x7fffb0004bf0) at /home/tymon/devsec/krita/libs/image/kis_stroke_strategy_undo_command_based.cpp:131
#14 0x00007fffd495e59c in TransformStrokeStrategy::doStrokeCallback(KisStrokeJobData*) (this=0x55555bb90b50, data=0x7fffb0004bf0) at /home/tymon/devsec/krita/plugins/tools/tool_transform2/strokes/transform_stroke_strategy.cpp:350
#15 0x00007ffff5e988cc in non-virtual thunk to KisUpdateJobItem::run() () at /usr/include/c++/8/bits/atomic_base.h:295
#16 0x00007ffff466af71 in  () at /usr/lib/x86_64-linux-gnu/libQt5Core.so.5
#17 0x00007ffff4672c87 in  () at /usr/lib/x86_64-linux-gnu/libQt5Core.so.5
#18 0x00007ffff206e164 in start_thread (arg=<optimized out>) at pthread_create.c:486
#19 0x00007ffff433bdef in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:95
Comment 20 Halla Rempt 2020-01-08 14:14:15 UTC
Git commit 47423c9abab188a53c4003a09ce6bdf0824baef9 by Boudewijn Rempt, on behalf of Dmitry Kazakov.
Committed on 08/01/2020 at 14:13.
Pushed by rempt into branch 'krita/4.2'.

Fix a crash when cancelling Transform Tool action

The crash happens only on systems that have asserts enabled, that
is, don't have NDEBUG defined.

Binding uninitialized '*m_savedTransformArgs' to a cont-reference
generated valid c++ code (a reference initialized with nullptr),
and given that finishStrokeImpl() didn't try to use/dereference
this reference, the code worked fine and didn't crash on systems
without asserts.

But on systems with asserts enabled (non NDEBUG), boost::optional
triggered a sanity check assert for dereferencing nullptr and crashed
the application.

The patch removes entire code for resetting m_savedTransformArgs in
cancelStrokeCallback(). It was actually an artifact of some initial
refactoring.

Thanks Fredrik Hansson for pointing out the problem!
https://invent.kde.org/kde/krita/merge_requests/197
(cherry picked from commit 2dc2ed5f5a6be2b81aab5001de8389e3f3cbdcac)

M  +1    -8    plugins/tools/tool_transform2/strokes/transform_stroke_strategy.cpp

https://invent.kde.org/kde/krita/commit/47423c9abab188a53c4003a09ce6bdf0824baef9
Comment 21 Halla Rempt 2020-01-08 14:28:19 UTC
Um... Now I can make the content of a layer
Comment 22 Halla Rempt 2020-01-08 14:29:35 UTC
completely disappear by first painting, then clicking the transform tool, then the move tool:

SAFE ASSERT (krita): "!m_strokeEnded || m_isCancelled" in file /home/boud/dev/krita/libs/image/kis_stroke.cpp, line 84
SAFE ASSERT (krita): "!m_strokeEnded || m_isCancelled" in file /home/boud/dev/krita/libs/image/kis_stroke.cpp, line 84
SAFE ASSERT (krita): "!m_strokeEnded || m_isCancelled" in file /home/boud/dev/krita/libs/image/kis_stroke.cpp, line 84

There's still something extremely fishy going on, and my commit making a safe assert on this line very probably is wrong.
Comment 23 Tiar 2020-01-08 14:39:09 UTC
Note: there are also bug 402770 and bug 408057 that might be responsible for that.
Comment 24 Tiar 2020-01-14 22:15:18 UTC
Git commit 8ef04427c4b8e63265ab4bb3456659cf4b0d39a4 by Agata Cacko.
Committed on 14/01/2020 at 22:14.
Pushed by tymond into branch 'master'.

Initialize transform tool args when ending stroke

Before this commit, transform tool would get an
assert when switching to another tool without
any changes.
This commit removes trying to cancel the stroke
in the finishStrokeCallback() call
and initializes m_savedTransformArgs so the finishing
can happen as always.

WARNING: it probably isn't the "proper" solution
for this issue. It does work correctly, but it adds
an unnecessary undo step in the situation when cancelling
should be used instead of finishing the stroke
(for example when the user switches to transform tool
and then immediately to another tool without making any changes).
Related: bug 415625

M  +25   -0    plugins/tools/tool_transform2/strokes/transform_stroke_strategy.cpp

https://invent.kde.org/kde/krita/commit/8ef04427c4b8e63265ab4bb3456659cf4b0d39a4
Comment 25 Tiar 2020-01-19 22:47:10 UTC
*** Bug 416468 has been marked as a duplicate of this bug. ***
Comment 26 Halla Rempt 2020-01-28 09:50:27 UTC
Git commit 4ec9beafc1d40205b82aa50dc6f981cc10891d0f by Boudewijn Rempt, on behalf of Agata Cacko.
Committed on 28/01/2020 at 09:09.
Pushed by rempt into branch 'krita/4.2'.

Initialize transform tool args when ending stroke

Before this commit, transform tool would get an
assert when switching to another tool without
any changes.
This commit removes trying to cancel the stroke
in the finishStrokeCallback() call
and initializes m_savedTransformArgs so the finishing
can happen as always.

WARNING: it probably isn't the "proper" solution
for this issue. It does work correctly, but it adds
an unnecessary undo step in the situation when cancelling
should be used instead of finishing the stroke
(for example when the user switches to transform tool
and then immediately to another tool without making any changes).
Related: bug 415625
(cherry picked from commit 8ef04427c4b8e63265ab4bb3456659cf4b0d39a4)

M  +25   -0    plugins/tools/tool_transform2/strokes/transform_stroke_strategy.cpp

https://invent.kde.org/kde/krita/commit/4ec9beafc1d40205b82aa50dc6f981cc10891d0f