-
-
Notifications
You must be signed in to change notification settings - Fork 21.4k
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 generating thumbnails for certain texture types #91768
Conversation
I'm not sure about the safety of doing forced |
It's most definitely a hack. I was hoping somebody could chime in with a better solution. |
I suspect this is caused by the generation not doing proper thread safety, the freeing of the texture shouldn't happen on a thread, so something should be done about that side instead I'd say |
As far as I can tell the allocation/deallocation is likely happening here: godot/editor/editor_resource_preview.cpp Lines 62 to 73 in c4279fe
When that |
Then that should probably be called on the main thread, loading shouldn't be done on a thread anyway AFAIK |
But again, this hinges on me not having misunderstood the actual cause for this crash. |
Although, I suppose |
Using |
The issue is similar to what I'm trying to address in #91630. Certain resource types do a deferred call as some final readyness step (such as generating the underlying shader of a materials or generating the data for a procedural texture). The issue is that the way In this case, it's fine that the resource previewer loads the resource from its thread, the problem being a race condition in the aforementioned mechanism (still not sure exactly what). In order to provide an universal fix for this so the resource previewer doesn't need to apply any ad hoc workaround, we could just try to let all those deferred updates happen on the thread that did the loading. We could, for safety, restrict it for now to certain resource types known to be safe in that regard, via some getter. That said, I have yet to reason about the implications of such an approach in many-threaded loads. A simpler fix for now would be to the resource previewer wait untill the main call queue is flushed before going on with the generation of the preview. |
Currently, |
What would this look like exactly? I'm assuming you would need to block in |
There's also potentially the issue that you can register your own custom preview generators in "user space", using |
Something I stated here (or in private discussion) was inaccurate: #91630 will also affect these resources because the resource loader from now on will flush its own call queue in-thread instead of transferring to the main one. That means that the procedural textures will be generated as part of loading them, which should avoid the race condition. @mihe Can you test if the issue is still a thing in current |
@RandomShaper Does this apply even though Maybe setting an override like that for the |
Ah, nevermind, I misread the code it seems. I see now that it calls I'll go ahead and close this then. Thank you! |
Fixes #58818.
Fixes #69861.
Fixes #70974.
This is unlikely to be an acceptable fix for this, but I figured this could maybe start a conversation about what else can be done.
I'm able to reproduce the above linked issue in a fairly big project, even on latest
master
, which is c4279fe as of writing this. The repro is unfortunately not consistent at all. Sometimes I can start the editor dozens of time without any issue, with or without an existing thumbnail cache, whereas other times the crash can happen several times in a row. Everything seems to point towards a multi-threaded race condition of some sort.The symptoms seem pretty straight-forward to me. The queued update of these texture types (although there may be more resource types like this) are sometimes called after the instance has been deallocated. I can say with 100% certainty that the instance has indeed been deallocated at that point, but I can't say exactly what allocated it, nor what deallocated it. Any attempts at logging stuff seems to add enough stalls that the race condition doesn't manifest itself anymore.
Seeing as how the
ObjectID
check inCallableCustomMethodPointer::call
(seen here) should prohibit this from ever happening as long as everything's done on a single thread, it stands to reason that this is happening because another thread (likeEditorResourcePreviewGenerator
) is allocating these resources, thus scheduling the deferred call, and then happens to deallocate them right asCallableCustomMethodPointer::call
is being invoked, after the above mentionedObjectID
check. The fact that this issue can also be reproduced by hovering over an editor tab seems to imply thatEditorResourcePreviewGenerator
is indeed the culprit, presumablyEditorResourcePreviewGenerator::generate_from_path
.This PR fixes this in a somewhat brute-force manner, by simply allowing the resource instances to always outlive their deferred call, by bumping their reference counter for the duration of it. I have been unable to reproduce the crash with this PR applied.
If my diagnosis seems incorrect, or if there's a better fix, I'd love to know.
(I suppose it's also possible that this fix instead leads to memory leaks at shutdown if for some reason the message queue isn't flushed after one of these texture updates is queued up.)