Are blueprint graph VMs safe for concurrent use

Is the blueprint VM intended to be concurrency safe?

Ie. Should it be safe to call 2 BlueprintImplementable / BlueprintNative functions from separate threads on the same UObject?

In our title we are running a deterministic gameplay simulation, utilizing the callbacks provided by Chaos::FPhysicsSolver

Input processing and simulation can happen in parallel from different threads

In our title we’re handling both input processing and deterministic gameplay for a Pawn in Blueprint through BlueprintImplementableEvent’s, we’ve started to hit a rare crash in our game with functions being called from the wrong thread, when we look at the callstack, it appears that the input processing event in blueprint ends up executing the simulation event.

This happens more frequently at low frame rates, where we run more simulations per frame, which would make it more likely that we run this in parallel to the input processing event.

Looking at the code in ScriptCore, we noticed there’s a “PersistentUberGraphFrame” that is re-used by the object, it is used as the “Locals” variable for the FFrame - I’m not familiar at all with the internals of the Blueprint VM, and haven’t found much on blueprint concurrency online

I did find somebody reporting similar behavior introduced in UE 4.21 [PersistentUberGraphFrame issues (causing crashes) in [Content removed]

And this line is eerily similar to what we’re seeing

> After quite a bit of digging we have ended up catching our BP code executing the wrong blueprints (seemingly inexplicably).

Is it possible that the shared usage of PersistentUberGraphFrame could cause the wrong graph event to be executed if 2 events were run in parallel?

Steps to Reproduce

  • Have multiple BlueprintImplementableEvent’s in a single graph
  • Call these events from multiple threads at the same time
  • Maybe blueprint callstack gets corrupted?

Hi Darcy,

Generally speaking, no, the Blueprint VM is not threadsafe. Blueprint graphs have access to a whole host of functions that can mutate state of UObjects. It’s intended to run solely on the game thread. So the behavior that you’re seeing isn’t entirely surprising.

That being said, AnimBPs are threadsafe, but that’s only because it’s a custom editor that restricts function calls that are tagged with “threadsafe”.

Thanks,

Dave

Hey Dave,

Thanks for the speedy response

I fully understand that the functions we call from blueprint can be non-thread safe, that’s not a concern, we’re very intentional in our events to only call game thread safe functions on game thread, and physics thread safe functions on physics thread

More curious about the VM itself, as the behavior we’re seeing seems to be that a function pointer is being overwritten - or we’re incorrectly continuing to iterate through the graph instead of ending where the event we called should end

I’ve attached a screenshot as a reference, the callstack we get shows “Update Driving Mode Components” being called by “Update Inputs from Player Controller” (For context the SimulateVehicle function here is the only reference the the “Update Driving Mode Components” blueprint function

From that thread that you linked:

> As described in the code it’s not safe to use the persistent frame off the game thread as parallel execution of the BP could lead to problems (which is exactly what we are seeing).

That’s almost certainly the problem that you’re seeing. The uber graph frame is not threadsafe. You can try disabling it via the bPersistentUberGraphFrame toggle, but that path is almost never tested. I do want to reiterate that using the BP VM on multiple threads gets a bit dicey, and it’s not something that we support.