landelare / ue5coro

A C++20 coroutine implementation for Unreal Engine 5 that feels almost native.
BSD 3-Clause Clear License
543 stars 48 forks source link

Is it dangerous for the UObject to be destroyed without canceling the coroutine? #17

Closed aziogroup closed 9 months ago

aziogroup commented 9 months ago

While testing the coroutine, the following code sometimes causes a crash when the PIE is terminated. Also, if you are lucky and it does not crash, it seems that the coroutine continues to run even though the PIE has terminated. It seemed to be no problem if I explicitly called cancel with EndPlay, etc.

You can easily reproduce this by specifying gc.CollectGarbageEveryFrame 1.

Does the coroutine need to explicitly call cancel?

Thank you.

#include "TestActor.h"
#include "UE5Coro.h"

// -------- UTestObject. ------------- //
FAsyncCoroutine UTestObject::CoStart(UObject* Caller)
{
    TestValue = 0.1f;
    co_await UE5Coro::Latent::Seconds(1.0f);
}

// -------- ATestActor. ------------- //
void ATestActor::BeginPlay()
{
    Super::BeginPlay();

    Object = NewObject<UTestObject>();
    CoStart();
}

FAsyncCoroutine ATestActor::CoStart()
{
    // Coroutine Start.
    co_await UE5Coro::Latent::NextTick();
    co_await Object->CoStart(this);
    co_await UE5Coro::Latent::Seconds(Object->TestValue);

    // Loop.
    CoStart();
    co_return;
}
landelare commented 9 months ago

Your coroutine is not latent, so you don't get latent this protection. This is by design and documented.

aziogroup commented 9 months ago

Thank you for your answer, sorry I did not learn enough. Using ForceLatentCoroutine solved the problem, Thank you! https://github.com/landelare/ue5coro/blob/master/Docs/Async.md