Commit 279bf5c7 authored by Dmitry Kazakov's avatar Dmitry Kazakov
Browse files

Fix a crash when trying to filter an active selection

The problem happens when the selection gets converted from a vector
form into a raster one as a part of the filter stroke. Then cancelling
the stroke recovers an old datamanager and, potentially, removes the
temporary one.

Now this datamanager removal is done in a safe way via the GUI thread,
like the shape selection.

BUG:455844
parent 48bf920f
Pipeline #197356 passed with stage
in 53 minutes and 28 seconds
......@@ -38,7 +38,8 @@ struct Q_DECL_HIDDEN KisSelection::Private {
{
}
static void safeDeleteShapeSelection(KisSelectionComponent *shapeSelection, KisSelection *selection);
template <typename T>
static void safeDeleteShapeSelection(T *object, KisSelection *selection);
// used for forwarding setDirty signals only
KisNodeWSP parentNode;
......@@ -56,12 +57,13 @@ struct Q_DECL_HIDDEN KisSelection::Private {
QReadWriteLock shapeSelectionPointerLock;
};
void KisSelection::Private::safeDeleteShapeSelection(KisSelectionComponent *shapeSelection, KisSelection *selection)
template <typename T>
void KisSelection::Private::safeDeleteShapeSelection(T *object, KisSelection *selection)
{
struct ShapeSelectionReleaseStroke : public KisSimpleStrokeStrategy {
ShapeSelectionReleaseStroke(KisSelectionComponent *shapeSelection)
ShapeSelectionReleaseStroke(T *object)
: KisSimpleStrokeStrategy(QLatin1String("ShapeSelectionReleaseStroke")),
m_shapeSelection(shapeSelection)
m_objectWrapper(makeKisDeleteLaterWrapper(object))
{
setRequestsOtherStrokesToEnd(false);
setClearsRedoOnStart(false);
......@@ -71,9 +73,17 @@ void KisSelection::Private::safeDeleteShapeSelection(KisSelectionComponent *shap
this->enableJob(JOB_CANCEL, true, KisStrokeJobData::BARRIER);
}
~ShapeSelectionReleaseStroke()
{
/// it looks like the strategy has not been executed,
/// the object will leak...
KIS_SAFE_ASSERT_RECOVER_NOOP(!m_objectWrapper);
}
void finishStrokeCallback() override
{
makeKisDeleteLaterWrapper(m_shapeSelection)->deleteLater();
m_objectWrapper->deleteLater();
m_objectWrapper = 0;
}
void cancelStrokeCallback() override
......@@ -82,7 +92,7 @@ void KisSelection::Private::safeDeleteShapeSelection(KisSelectionComponent *shap
}
private:
KisSelectionComponent *m_shapeSelection = 0;
KisDeleteLaterWrapper<T*> *m_objectWrapper = 0;
};
/**
......@@ -114,8 +124,8 @@ void KisSelection::Private::safeDeleteShapeSelection(KisSelectionComponent *shap
*/
struct GuiStrokeWrapper
{
GuiStrokeWrapper(KisImageSP image, KisSelectionComponent *shapeSelection)
: m_image(image), m_shapeSelection(shapeSelection)
GuiStrokeWrapper(KisImageSP image, T *object)
: m_image(image), m_object(object)
{
}
......@@ -124,15 +134,15 @@ void KisSelection::Private::safeDeleteShapeSelection(KisSelectionComponent *shap
KisImageSP image = m_image;
if (image) {
KisStrokeId strokeId = image->startStroke(new ShapeSelectionReleaseStroke(m_shapeSelection));
KisStrokeId strokeId = image->startStroke(new ShapeSelectionReleaseStroke(m_object));
image->endStroke(strokeId);
} else {
delete m_shapeSelection;
delete m_object;
}
}
KisImageWSP m_image;
KisSelectionComponent *m_shapeSelection;
T *m_object;
};
if (selection) {
......@@ -144,14 +154,14 @@ void KisSelection::Private::safeDeleteShapeSelection(KisSelectionComponent *shap
}
if (image) {
makeKisDeleteLaterWrapper(new GuiStrokeWrapper(image, shapeSelection))->deleteLater();
shapeSelection = 0;
makeKisDeleteLaterWrapper(new GuiStrokeWrapper(image, object))->deleteLater();
object = 0;
}
}
if (shapeSelection) {
makeKisDeleteLaterWrapper(shapeSelection)->deleteLater();
shapeSelection = 0;
if (object) {
makeKisDeleteLaterWrapper(object)->deleteLater();
object = 0;
}
}
......@@ -169,6 +179,10 @@ struct KisSelection::ChangeShapeSelectionCommand : public KUndo2Command
if (m_shapeSelection) {
Private::safeDeleteShapeSelection(m_shapeSelection, m_selection ? m_selection.data() : 0);
}
if (m_reincarnationCommand) {
Private::safeDeleteShapeSelection(m_reincarnationCommand.take(), m_selection ? m_selection.data() : 0);
}
}
void undo() override
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment