Page MenuHome

Fix T87090: VSE scrubbing locks up blender
ClosedPublic

Authored by Richard Antalik (ISS) on Apr 7 2021, 12:17 PM.

Details

Summary

Speed effect caused , that some raw frames are re-used for multiple
final frames. When cached final frame is freed due to memory being
full, it tried to free also lower level cached frames that were used
during compositing. Some lower level cached frames were already freed
by different final frame and BLI_ghash_remove() failed.

When BLI_ghash_remove() fails, stop traversing "child" cached frames.

Diff Detail

Repository
rB Blender
Branch
T87090 (branched from master)
Build Status
Buildable 13946
Build 13946: arc lint + arc unit

Event Timeline

Richard Antalik (ISS) requested review of this revision.Apr 7 2021, 12:17 PM
Richard Antalik (ISS) created this revision.

Am I right that if the base is not in the hash its memory has been freed, which will cause use-after-free at`next = base->link_next`?

Am I right that if the base is not in the hash its memory has been freed, which will cause use-after-free at`next = base->link_next`?

Yes, that is true. It never happens though, because seq_cache_recycle_linked() is _only_ used for final images and therefore base->link_next is always NULL. There is one usage where it's run if SeqCacheItem->ibuf == NULL which should never happen.

I think that code could be removed.

Honestly I would rather remove this whole linking system. It's only purpose was to aid with invalidation. Now for some time I have not seen any reports that invalidation is not working correctly. But I don't want to remove it at the end of BCON2 really as it may uncover bugs that will take time to discover again.

Afraid I'm a bit more confused now :( There is also SeqCacheKey *prev = base->link_prev;. So, if the base is not in the cache->hash, can its content be trusted? Or should it be changed to something like:

while (base) {
  if (base is not in cache->hash) {
    break;
  }
  SeqCacheKey *prev = base->link_prev;
  BLI_ghash_remove ...
  base = prev;
}

?

Afraid I'm a bit more confused now :( There is also SeqCacheKey *prev = base->link_prev;.

Sorry it turns out that I was wrong previously. Because if base is freed by seq_cache_keyfree, it remains in memory until it is replaced by different key or by seq_cache_destruct().

So, if the base is not in the cache->hash, can its content be trusted?

Since key can be replaced, approach in this patch will start to remove random keys, which I have confirmed when I enable cache visualization.

Not sure what would be the best solution. I could add usercount to SeqCacheKey, but that would be relatively risky change on par with removing this linking system altogether. I will think about some other solutions.

Check whether key exists in ghash and whether it has been overwritten by new one.

Is probably fine, but this system is rather cryptic to me. Mix of hash and linked list.. Just make sure you aren't fighting race condition here, because that'd require different solution.

I'd also use BLI_ghash_haskey as it semantically a better fit.

Use BLI_ghash_haskey to check if key exists in cache

Is probably fine, but this system is rather cryptic to me. Mix of hash and linked list.. Just make sure you aren't fighting race condition here, because that'd require different solution.

It is a bit cryptic... But when speed effect is used, raw images can be rendered for random frame, this seemed like good solution to follow keys when removing final one. Probably it would be more sensible to explicitly store frame in which these keys were created, but that will require some modifications.
It's definitely not a race condition.

From the code seems fine. The logic I can not really review.

Suggestion: get the issue fixed, and make this piece of code less cryptic in the future ;)

This revision is now accepted and ready to land.Apr 22 2021, 12:20 PM
This revision was automatically updated to reflect the committed changes.