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

Fix crash when activating non-initial song then opening document with expansion chip(s) #148

Merged
merged 1 commit into from
Jun 23, 2022

Conversation

nyanpasu64
Copy link
Collaborator

@nyanpasu64 nyanpasu64 commented Jun 10, 2022

CFamiTrackerDoc::OpenDocumentNew() and other functions can call CFamiTrackerDoc::SetupChannels(). If the new document contains expansion chips, it calls CFamiTrackerDoc::SetMachine() during the middle of updating the document. Previously this could call CDocument::UpdateAllViews() (a method which has no right to exist), trying to redraw the pattern editor mid-load, when the number of songs has already been reset to 1 but the active song/track is still unchanged. If you previously picked a non-initial song, CPatternEditor::GetFrameCount() calls m_pDocument->GetFrameCount(GetSelectedTrack()), which indexes out of bounds.

The "solution" is to add a boolean parameter to CFamiTrackerDoc::SetMachine(), to skip redrawing if the document is in an inconsistent state. I would not be surprised if there are other crashes lurking undiscovered.

Of course the real fix is to make observing inconsistent state difficult to impossible by design, by creating a StateTransaction-style type which reloads program state exactly once, after all changes have been made and the program is in a consistent state. But FamiTracker is too complex to rewrite state management entirely.

Fixes #147.

@nyanpasu64 nyanpasu64 changed the title Fix crash when activating non-initial song then opening document Fix crash when activating non-initial song then opening document with expansion chip(s) Jun 23, 2022
… expansion chip

CFamiTrackerDoc::OpenDocumentNew() and other functions can call
CFamiTrackerDoc::SetupChannels() -> CFamiTrackerDoc::SetMachine
(), during the middle of updating the document. Previously this could
call CDocument::UpdateAllViews() (a method which has no right to
exist), trying to redraw the pattern editor mid-load, when the number
of songs has already been reset to 1 but the active song/track is still
unchanged. If you previously picked a non-initial song,
CPatternEditor::GetFrameCount() calls m_pDocument->GetFrameCount
(GetSelectedTrack()), which indexes out of bounds.

The "solution" is to add a boolean parameter to
CFamiTrackerDoc::SetMachine(), to skip redrawing if the document is in
an inconsistent state. Of course the real fix is to create a
StateTransaction-style type which reloads program state exactly once,
after all changes have been made and the program is in a consistent
state. But FamiTracker is too complex to rewrite state management
entirely.
@nyanpasu64 nyanpasu64 force-pushed the fix-open-song-crash branch from a525a86 to bff3dc4 Compare June 23, 2022 11:46
@nyanpasu64 nyanpasu64 merged commit b98325e into master Jun 23, 2022
@nyanpasu64 nyanpasu64 deleted the fix-open-song-crash branch June 23, 2022 12:11
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.

Opening existing document when non-initial song is active crashes
1 participant