Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[MU4] Fix GH#10653: Crash converting to whole note #10654

Closed

Conversation

Jojo-Schmitz
Copy link
Contributor

Resolves: #10653

Same issue with (and originally reported for) MU3

@Jojo-Schmitz Jojo-Schmitz changed the title [MU4] Fix GH10653: Crash converting to whole note [MU4] Fix GH#10653: Crash converting to whole note Feb 23, 2022
Jojo-Schmitz added a commit to Jojo-Schmitz/MuseScore that referenced this pull request Feb 23, 2022
twice, on a certain score.

Backport of musescore#10654
Jojo-Schmitz added a commit to Jojo-Schmitz/MuseScore that referenced this pull request Feb 24, 2022
twice, on a certain score.

Backport of musescore#10654
Jojo-Schmitz added a commit to Jojo-Schmitz/MuseScore that referenced this pull request May 12, 2022
twice, on a certain score.

Backport of musescore#10654
@Tantacrul
Copy link
Contributor

Cool! Just tested it and it seems to be solving the crash. @RomanPudashkin / @Eism - if you are happy with this, it would be nice to merge (removes a P0).

Thanks @Jojo-Schmitz !

@Jojo-Schmitz
Copy link
Contributor Author

What about merging this?

@Jojo-Schmitz
Copy link
Contributor Author

Any particular reason not to merge this?

@Tantacrul
Copy link
Contributor

@bkunda - when you get a moment, can you test this and assuming all's good, recommend to merge?

I can't quite manage it at the mo.

@bkunda
Copy link

bkunda commented Sep 2, 2022

@bkunda - when you get a moment, can you test this and assuming all's good, recommend to merge?

I can't quite manage it at the mo.

The logs for this run have apparently expired so I can no longer download any artifacts.

@Jojo-Schmitz
Copy link
Contributor Author

Downside of letting PRs sit for such a long time...
Rebased and force-pushed now.

@@ -4830,6 +4830,9 @@ static EngravingItem* findLinkedVoiceElement(EngravingItem* e, Staff* nstaff)
Measure* measure = segment->measure();
Measure* m = score->tick2measure(measure->tick());
Segment* s = m->findSegment(segment->segmentType(), segment->tick());
if (!s) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks very suspicious. Where do these null pointers come from? It looks like this PR fixes the consequence of the problem, not the cause

Copy link
Contributor Author

@Jojo-Schmitz Jojo-Schmitz Sep 2, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, I don't quite understand the question, obviously this one comes from findSegment().

That in turn used findSegmentR()

//---------------------------------------------------------
//   findSegmentR
//    Search for a segment of type st at measure relative
//    position t.
//---------------------------------------------------------

Segment* Measure::findSegmentR(SegmentType st, const Fraction& t) const
{
    Segment* s;
    if (t > (ticks() * Fraction(1, 2))) {
        // search backwards
        for (s = last(); s && s->rtick() > t; s = s->prev()) {
        }
        while (s && s->prev() && s->prev()->rtick() == t) {
            s = s->prev();
        }
    } else {
        // search forwards
        for (s = first(); s && s->rtick() < t; s = s->next()) {
        }
    }
    for (; s && s->rtick() == t; s = s->next()) {
        if (s->segmentType() & st) {
            return s;
        }
    }
    return 0;
}

Which indeed may return a nullptr.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why does it return null in this case? It usually indicates some other, more complicated problem

Copy link
Contributor Author

@Jojo-Schmitz Jojo-Schmitz Sep 2, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Dunno. The method does on occasions and on purpose return a nullptr. So callers should take care of those and not relying on it to never do that.

If it were illegal, an assert() would be due in that findSegmentR(), wouldn't it?

@RomanPudashkin
Copy link
Contributor

It took me some time to figure out the real cause of the crash, and now I understand it.

For example, the user selects a measure with 4 quarter notes and clicks on the whole-note button in the note input bar:

  1. Score::padToggle calls Score::changeCRlen for each selected chord.

  2. changeCRlen can automatically deselect the score and select notes. So, on the first iteration (one iteration for each chord) it deselects the previously selected measure and selects the first chord in it.

  3. changeCRlen removes all the chords in the measure (using undo(new RemoveElement(...))), but keeps a pointer to the first chord (that was selected in the previous step) and keeps re-selecting it at each iteration

  4. Thus, after using Score::padToggle, the selection still contains the pointer to the already removed chord

@RomanPudashkin
Copy link
Contributor

RomanPudashkin commented Sep 5, 2022

This PR fixes one symptom of the problem (crash in one scenario), but it doesn't fix the problem completely (removed element in the selection). For example, if I cherry-pick the changes from the PR, I can't select anything in the note input bar after the steps from the issue (due to the corrupted selection list). I guess we will be able to reproduce this crash in other scenarios as well (even with the fix from the PR)

@Jojo-Schmitz
Copy link
Contributor Author

Jojo-Schmitz commented Sep 5, 2022

Ah, I see.
Don't see the fix for that though :-(
Still won't invalidate my pointer checking in this PR, would it?

Or should that function never return 0 and that needs to get checked and prevented right there?

@RomanPudashkin
Copy link
Contributor

Let's try this fix #13183

It prevents removed elements from being added to the selected element list

@Jojo-Schmitz
Copy link
Contributor Author

Jojo-Schmitz commented Sep 5, 2022

That's fine, and of course better than my attempt here, but #13183 still allows Measure::findSegmentR() to return 0, which still may cause a crash whenever the return value of this is dereferenced. Should be prevented by an assert() at least.

@Jojo-Schmitz Jojo-Schmitz deleted the crash-change-duration branch September 5, 2022 20:02
Jojo-Schmitz added a commit to Jojo-Schmitz/MuseScore that referenced this pull request Mar 5, 2023
twice, on a certain score.

Backport of musescore#10654
Jojo-Schmitz added a commit to Jojo-Schmitz/MuseScore that referenced this pull request Apr 10, 2024
Backport of musescore#22314

Seems to build upon an backport of musescore#10654, which got closed in favor of musescore#13183
Jojo-Schmitz pushed a commit to Jojo-Schmitz/MuseScore that referenced this pull request Apr 10, 2024
Backport of musescore#22314

Seems to build upon an backport of musescore#10654, which got closed in favor of musescore#13183
Jojo-Schmitz pushed a commit to Jojo-Schmitz/MuseScore that referenced this pull request Apr 11, 2024
Backport of musescore#22314

Seems to build upon an backport of musescore#10654, which got closed in favor of musescore#13183
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[MU3 and MU4 Issue] Crash while converting to whole note
4 participants