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 a crash and clean up YACReaderFlowGL #198

Open
wants to merge 4 commits into
base: develop
Choose a base branch
from

Conversation

vedgy
Copy link
Contributor

@vedgy vedgy commented Feb 6, 2021

See the commit messages for details.

Adjusting index of the item that is about to be removed is pointless.
Not adjusting the last index caused an assertion failure (a crash) in
Library built in Debug mode - when a comic other than the last in the
current folder was deleted in ClassicComicsView with hardware
acceleration enabled.
The implementation when item != -1 seems to leak images[item].texture.
Let us remove rather than fix this unused branch.

Make YACReaderFlowGL::insert()'s name argument const.
This index was used only in YACReaderFlowGL::drawCover(). A simple
change of this function eliminates the use.

The benefits of the removal:
* sizeof(YACReader3DImage) is 8 bytes less now, which improves CPU cache
  utilization and saves a little RAM;
* the code, which ensured that this index member matches the index of
  the image in YACReaderFlowGL::images, can be removed now;
* the index member can no longer get out of sync with the index of the
  image.

Simplify the implementation of YACReaderFlowGL::draw().

For some (most likely obsolete) reason YACReaderFlowGL::replace()
checked if the index member matches the index of the image and handled
the mismatch differently. I don't see how the mismatch could happen with
the current implementation of YACReaderFlowGL and I couldn't trigger it
during debugging. So I think this special case can be safely removed.
@vedgy
Copy link
Contributor Author

vedgy commented Feb 6, 2021

There is also a crash on exit from YACReader Library after removing a comic or a folder. I have already fixed it and will create a pull request soon.

@luisangelsm
Copy link
Member

How did you tested it? Moving quickly between folders in YACReaderLibrary, or fast opening next/previous comic in YACReader while the flow is shown (using CTRL + Left/Right) can be good ways of testing this.

I have some memories about the worker loading an image from the previous content while the flow is repopulated, causing a wrong image being displayed in the flow, because once the right one finishes loading the flow will reject it because it thinks it is already loaded.

@vedgy
Copy link
Contributor Author

vedgy commented Feb 6, 2021

How did you tested it? Moving quickly between folders in YACReaderLibrary, or fast opening next/previous comic in YACReader while the flow is shown (using CTRL + Left/Right) can be good ways of testing this.

Just tested Library and Reader like you described at this branch. Haven't spotted a wrong image near the beginning. But detecting that a wrong image is displayed somewhere far from the first one is obviously difficult.

I have some memories about the worker loading an image from the previous content while the flow is repopulated, causing a wrong image being displayed in the flow, because once the right one finishes loading the flow will reject it because it thinks it is already loaded.

Your description resembles a symptom of a thread safety bug. Sadly, in the presence of data races any refactoring or fix can cause a regression. I still plan to implement a follow-up pull request to #99. But I have forgotten the details of that fix/refactoring, so not sure whether it would guarantee thread safety here.

loaded[idx] is unconditionally set to true in the call to
YACReaderFlowGL::replace() just before the removed line.
@luisangelsm
Copy link
Member

Sadly, in the presence of data races any refactoring or fix can cause a regression.

That's why I usually don't like changing code just for the sake of it. This worker implementation comes from the original PictureFlow implementation, and it's been years since I touched it. So I don't think the benefits of these kind of changes are worth the risks.

But I am happy to see the crash fixed :), nice catch!

@vedgy
Copy link
Contributor Author

vedgy commented Feb 7, 2021

This pull request does not touch the workers. The changes here seem to be pretty safe to me. The removed if (images[item].index == item) check in YACReaderFlowGL::replace() looks like a leftover from a different implementation, because the current code in develop consistently updates the index data member on each insertion/removal/reordering in YACReaderFlowGL::images. Except for the one place that crashes in Debug mode.

That's why I usually don't like changing code just for the sake of it. This worker implementation comes from the original PictureFlow implementation, and it's been years since I touched it. So I don't think the benefits of these kind of changes are worth the risks.

My reimplementation of ComicFlow's worker doesn't seem to be causing issues in YACReader 9.7, does it? Keeping the old code intact when it can be proven to be thread-unsafe isn't a viable long-term strategy. Things can break on a compiler or framework or hardware update. And it will be difficult to figure out what exactly is happening and how to fix it. Best to get rid of data races altogether. Encapsulating and unifying multithreading code makes this easier by eliminating the need to analyze duplicate code and allowing to inspect loosely coupled classes more or less separately.

@vedgy
Copy link
Contributor Author

vedgy commented Feb 10, 2021

I have some memories about the worker loading an image from the previous content while the flow is repopulated, causing a wrong image being displayed in the flow, because once the right one finishes loading the flow will reject it because it thinks it is already loaded.

Just looked at the code again and realized that you might have confused the removed YACReader3DImage:index with a worker's idx (which is not affected by this pull request). The worker's idx is reset (set to -1) every time the data is changed. YACReaderFlowGL::loaded is adjusted too when a change happens. These ensure that a wrong image is not displayed. As far as I can tell, this code is completely unrelated to the removed index.

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.

None yet

2 participants