-
Notifications
You must be signed in to change notification settings - Fork 58
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
Latent Coroutine Resumes for Unloaded Streamed Actor, Crash #19
Comments
Update: |
Thank you for the detailed bug report! I managed to reproduce something similar myself. |
@nwilson100 is the |
@landelare The fix worked! I tested two cases for 1000 repeats with automation that reproduced consistently before (with the worst case at 1/10 repro rate). The first case I tested the fix against was the one shared with the report, and the second case involved a coroutine running in a UObject who had an actor component as its outer, then unloading the owning actor. Thanks for the fix and great work with this plugin. |
Thank you again for the detailed bug report, the fix will ship in 1.10. |
Context:
The issue occurs when using a latent coroutine (with
FForceLatentCoroutine
) on an Actor that gets unloaded as a result of asynchronously unloading a level using level streaming. Specifically in my case,UGameplayStatics::UnloadStreamLevelBySoftObjectPtr
.The apparent issue observed is that coroutines resume on actors that have been unloaded from the world. At the point of resuming, the
__coro_frame_ptr
's__this
points to the Actor that has been unloaded: TheirUWorld *
is null, and theirActorHasBegunPlay
data member has been set toHasNotBegunPlay
. While usingthis
appears to be a valid memory access, the coroutine has resumed for an actor who is no longer a part of anyUWorld
, resulting in crashes for any functionality that requires the actor to have a world. It's a validActor
in terms of existing in memory, but you certainly would not want to do anything with it at that point.I'm assuming this behavior is undesirable, as the latent coroutine continues running on the actor's original world that it was loaded into, despite that actor no longer existing in the world, but still existing in memory. While we have latent
this
protection, there doesn't seem to be protection against resuming on actors that have been unloaded and shouldn't be executing its usual gameplay code.Expected/Desired behavior:
Some mechanism should prevent coroutines from resuming if the owning Actor has been unloaded via streaming. Additionally, if possible, other
UObject
's who have that unloaded Actor set as theirOuter
will also have their coroutines cancelled in a way that prevents resuming, so they also are not left executing without aUWorld
in their outer chain or with an owner that shouldn't be used.Repro steps:
This issue reproduces for me 100% of the time.
FForceLatentCoroutine
.GetWorld()
frequently. My test usesco_await UE5Coro::Latent::Seconds
to accessGetWorld()
at an interval of 0.1 seconds.BeginPlay()
.UGameplayStatics::LoadStreamLevelBySoftObjectPtr
.UGameplayStatics::UnloadStreamLevelBySoftObjectPtr
.__coro_frame_ptr
and look into the data of__this
to see that object is in an unloaded state.ActorHasBegunPlay
will beHasNotBegunPlay
, and the Actor will have noUWorld
.The text was updated successfully, but these errors were encountered: