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 crash when changing project default token #1047

Merged
merged 2 commits into from
Feb 28, 2023
Merged

Conversation

joseph-kaile
Copy link
Collaborator

Fixes #1042. The problem was that a main thread task is calling Destroy Tileset. The tileset would destroy itself when calling dispatch main thread tasks.

@cesium-concierge
Copy link

Thanks for the pull request @joseph-kaile!

Reviewers, don't forget to make sure that:

@kring
Copy link
Member

kring commented Feb 28, 2023

Thanks @joseph-kaile. It took me a minute to realize why this works. The problem is that the SelectCesiumIonToken panel does some async work and thenInMainThread calls RefreshTileset on every tileset that uses the project default token. That main thread task can be - and often is - dispatched from inside the Tileset's updateView, so we're effectively destroying an object while we're executing one of its methods.

Your fix avoids this by blocking the button press callback until after the async work completes, guaranteeing that the continuation cannot be invoked from updateView because we simply won't invoke updateView until after the async work completes. This is obviously far better than the current situation (a crash), but it does mean the UI is unresponsive while we're talking to Cesium ion.

When I originally wrote this panel, we didn't have this problem because the UI used a completely separate AsyncSystem from the tilesets. So the SelectCesiumIonToken continuation could never be invoked from inside updateView because they used completely separate queues. I changed this in #958 as part of an effort to avoid making games freeze completely while destroying tilesets and waiting for async requests to complete. I'm not quite sure if that was essential for some reason, or if it just seemed like a good idea at the time.

So I'm going to merge this because better is better, particularly for releasing tomorrow. But I think longer term there are three ways we can avoid the freeze when changing the token:

  1. Make RefreshTileset smarter. If it detects its being called from inside an update, it defers the refresh.
  2. Instead of directly calling RefreshTileset from within a thenInMainThread, dispatch a main thread task using Unreal's AsyncTask(ENamedThreads::GameThread, ...). Unreal's tasks are guaranteed to be executed outside updateView, or any of our other code, so this will be safe and effective.
  3. Change cesium-native so that it doesn't call dispatchMainThreadTasks from within updateView. Instead, the game engine code would be expected to call it itself at a suitable time. I think this is my favorite because it should eliminate the potential for a whole class of bugs as well as being slightly more performant (because we don't dispatch main thread tasks for every tileset every frame).

I'll write a separate issue for this.

@kring
Copy link
Member

kring commented Feb 28, 2023

I switched back to using the panel-level promise and future rather than creating a local one in UseOrCreate. This should avoid potential problems when the panel is popped up in the course of adding a tileset.

@kring kring merged commit 13c89af into ue4-main Feb 28, 2023
@kring kring deleted the fix-token-switch branch February 28, 2023 12:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
3 participants