Crash when closing score

• Nov 27, 2014 - 01:32
Type
Functional
Severity
S2 - Critical
Status
closed
Project

1. Open attached score.
2. Hold Shift, then click all bars and staves of piano (selecting them).
3. 'Edit'>'Copy'.
4. Click on bar 1 of acoustic guitar.
5. 'Edit'>'Paste'.
6. 'File'>'Close'.

7. 'Don't Save'.

OR

7. 'Save' twice.
8. 'File'>'Close'.

Result: Crash.

Note: See attached log.

Using MuseScore 2.0 Nightly Build 2b9752b - Mac 10.7.5.


Comments

I can't reproduce under Linux Mint 17, commit ef0f49c0
BUT
I can reproduce if I run mscore with address sanitizer (and I think it could be reproducible also when mscore is run under valgrind).
It seems that there is an access to an already deleted object when freeing the undo queue when a chord was pasted over a tuplet.
Alternative steps:
1- Open attached file;
2- Select the second measure, and copy;
3- Select 4th measure and paste;
5- Close discarding the changes.

Attached address sanitizer log.

Attachment Size
crash_when_closing_log.txt 10.07 KB
Pasting_on_tuplet.mscz 3.11 KB

It happens that the tuplet in the undo stack is deleted before all of the elements referring to it are deleted. The _tuplet parameter of these elements is not set to zero when the tuplet is deleted because they do not belong to the element list (_elements) of the tuplet itself, probably because they belong to different undo-redo steps.
When the element referring to the tuplet are deleted, their _tuplet reference is not 0 and therefore the tuplet is being accessed to check if it is empty; but the tuplet object was already deleted.
What about deferring the deletion of the tuplet with a deleteLater() ?
I tried to modify the cleanup function at line 1631 of libmscore:
{syntaxhighlighter brush:c++;first-line:1631;}
void RemoveElement::cleanup(bool undo)
{
if (undo) {
qDebug("RemoveElement::cleanup: delete %d %s", undo, element->name());
if (element->type() != Element::Type::TUPLET) {
delete element;
element = 0;
}
else {
element->deleteLater();
element = 0;
}
}
}
{/syntaxhighlighter}
and under valgrind it does not give problems, and it deletes the tuplet after all the other elements (works also for nested tuplets).
However, I am not sure about turning this into a pull request since it looks some sort of hack rather than a proper solution (or not?). There may probably be better solution to this bug (but likely involving tampering with the undo queue).