We’re experiencing a blocker bug on the WSA platform. We’re using the old UnityEngine.Input API and not the newer UnityEngine.InputSystem API. This blocker issue does not appear in 2019.4.12f1. But it does manifest in 2019.4.19f. An upgrade to 2019.f.22f did not fix the issue. It appears the bug was introduced fairly recently. The bug is very, very easy to reproduce.
After typing rapidly into an Input text box or frequently just typing normally, the system freezes. I’ve run this in the VS 2019 debugger and narrowed down the root cause to a multi-threaded deadlock.
This issue reproduces consistently in our project. However I’ve reproduced the bug using Unity’s sample input text example.
public class InputProxy : MonoBehaviour
{
[SerializeField] private InputField Text;
// Start is called before the first frame update
void Start()
{
Keyboard.current.onTextInput += (char character) =>
{
Debug.Log($“Key pressed {character}”);
Text.text += character;
};
}
}
Thread A is deadlocked waiting for Thread B
Thread A (Waiting on lock owned by Thread B)
[Waiting on lock owned by Thread 35064, double-click or press enter to switch to thread]
ntdll.dll!NtWaitForAlertByThreadId()
ntdll.dll!RtlpWaitOnAddressWithTimeout()
ntdll.dll!RtlpWaitOnAddress()
ntdll.dll!RtlpWaitOnCriticalSection()
ntdll.dll!RtlpEnterCriticalSectionContended()
ntdll.dll!RtlEnterCriticalSection()
TextInputFramework.dll!CTextInputClientFreeThread::EditControlInfoChanged()
msctf.dll!CTextInputClientOwnerAdapter::EditControlInfoChanged()
msctf.dll!CTextInputClientWrapper::EditControlInfoChanged()
Windows.UI.Core.TextInput.dll!Windows::UI::Text::Core::CEditContext::put_IsReadOnly()
UnityPlayer.dll!winrt::impl::consume_Windows_UI_Text_Core_ICoreTextEditContext<struct winrt::Windows::UI::Text::Core::ICoreTextEditContext>::IsReadOnly(bool)
UnityPlayer.dll!uwp::ui::TextInputController::AcquireFocus(struct uwp::ui::TextBoxConfigration const &,class core::basic_string<wchar_t,class core::StringStorageDefault<wchar_t> > const &)
UnityPlayer.dll!uwp::ui::TextInputController::AcquireFocus(void)
UnityPlayer.dll!KeyboardOnScreenCoreTextEdit::SetActive(bool)
UnityPlayer.dll!KeyboardOnScreen::SetActive(bool)
UnityPlayer.dll!KeyboardOnScreen::SetText(class core::basic_string<char,class core::StringStorageDefault<char> >)
UnityPlayer.dll!TouchScreenKeyboard_Set_Custom_PropText(class ScriptingBackendNativeObjectPtrOpaque *,class ScriptingBackendNativeStringPtrOpaque *)
GameAssembly.dll!TouchScreenKeyboard_set_text_mF72A794EEC3FC19A9701B61A70BCF392D53B0D38(TouchScreenKeyboard_t2A69F85698E9780470181532D3F2BC903623FD90 * __this, String_t * ___value0, const MethodInfo * method) Line 29197
GameAssembly.dll!InputField_SetText_mEF14F85B3A852C7BB42625B5982DB4BFEBAF313F(InputField_t533609195B110760BCFF00B746C87D81969CB005 * __this, String_t * ___value0, bool ___sendCallback1, const MethodInfo * method) Line 33778
GameAssembly.dll!InputField_set_text_m281F692E6AC99F9AE94EFE140B8AB2AAB5C4ED19(InputField_t533609195B110760BCFF00B746C87D81969CB005 * __this, String_t * ___value0, const MethodInfo * method) Line 33454
GameAssembly.dll!InputProxy_U3CStartU3Eb__1_0_m04CF619389578C9F2C8DFE7994E9B1B5191FFBD2(InputProxy_t9622125E0A01B44A5C9E9079D2930D30F22E80A2 * __this, wchar_t ___character0, const MethodInfo * method) Line 3477
GameAssembly.dll!Action_1_Invoke_mC9191252CB273FF4B1E6BC7732B51B87755CF076_gshared(Action_1_t49CEE65271E77B0724B9809B1517C3095C59B004 * __this, wchar_t ___obj0, const MethodInfo * method) Line 21251
GameAssembly.dll!Action_1_Invoke_mC9191252CB273FF4B1E6BC7732B51B87755CF076(Action_1_t49CEE65271E77B0724B9809B1517C3095C59B004 * __this, wchar_t ___obj0, const MethodInfo * method) Line 18836
GameAssembly.dll!Keyboard_OnTextInput_mEAFCEFAF93966D07C0B5B90DEA8BEA84FA1EAE31(Keyboard_t32E5860C0A34C72A5FDD4B83D506C75CBF00F17C * __this, wchar_t ___character0, const MethodInfo * method) Line 34177
GameAssembly.dll!InterfaceActionInvoker1<wchar_t>::Invoke(unsigned int slot, Il2CppClass * declaringInterface, Il2CppObject * obj, wchar_t p1) Line 106
GameAssembly.dll!InputManager_OnUpdate_mCD0602D473BA35536EDBA570C2A76D1205A9867E(InputManager_tE2A938B45D056C780012C228D64A557963C98CBA * __this, int ___updateType0, InputEventBuffer_t368F34E2F1C4A605D6E9050EEC18C62767ABB448 * ___eventBuffer1, const MethodInfo * method) Line 40465
GameAssembly.dll!InputUpdateDelegate_Invoke_m7B31A33936860E7B3D11B83AA16E7D8A4D84FE85(InputUpdateDelegate_tD572CA50F8F785132B7B88ACCAB64A0E3C37F54A * __this, int ___updateType0, InputEventBuffer_t368F34E2F1C4A605D6E9050EEC18C62767ABB448 * ___eventBuffer1, const MethodInfo * method) Line 31307
GameAssembly.dll!U3CU3Ec__DisplayClass7_0_U3Cset_onUpdateU3Eb__0_mDE54F0ACA6A4DD6364550B941EF1A6B6E76C0BDB(U3CU3Ec__DisplayClass7_0_t1E73E3FC24A2D765A236DC14923AB070DEB33806 * __this, int ___updateType0, NativeInputEventBuffer_t9960648276F01C5C3435E0E6FD870F2DA8A132EF * ___eventBufferPtr1, const MethodInfo * method) Line 32578
GameAssembly.dll!NativeUpdateCallback_Invoke_m0F3B8F934AB1C953397B0E2134D17A9AAEBD975E(NativeUpdateCallback_tCC4B5A2692C21C00FC2FC1E4EC5280E98423B8D5 * __this, int ___updateType0, NativeInputEventBuffer_t9960648276F01C5C3435E0E6FD870F2DA8A132EF * ___buffer1, const MethodInfo * method) Line 1517
GameAssembly.dll!NativeInputSystem_NotifyUpdate_m9AAC791622BA97DC7807610DD08C54F6011834F2(int ___updateType0, __int64 ___eventBuffer1, const MethodInfo * method) Line 1240
GameAssembly.dll!RuntimeInvoker_FalseVoid_t22962CB4C05B1D89B55A6E1139F0E87A90987017_Int32_t585191389E07734F19F3156FF88FB3EF4800D102_IntPtr_t(void(*)() methodPointer, const MethodInfo * methodMetadata, void * obj, void * * args) Line 51329
GameAssembly.dll!il2cpp::vm::Runtime::Invoke(const MethodInfo * method, void * obj, void * * params, Il2CppException * * exc) Line 545
GameAssembly.dll!il2cpp_runtime_invoke(const MethodInfo * method, void * obj, void * * params, Il2CppException * * exc) Line 1075
UnityPlayer.dll!scripting_method_invoke(class ScriptingMethodPtr,class ScriptingObjectPtr,struct ScriptingArguments &,class ScriptingExceptionPtr *,bool)
UnityPlayer.dll!ScriptingInvocation::Invoke(class ScriptingExceptionPtr *,bool)
UnityPlayer.dll!ScriptingInvocation::Invoke<void>(class ScriptingExceptionPtr *,bool)
UnityPlayer.dll!Scripting::UnityEngineInternal::Input::NativeInputSystemProxy::NotifyUpdate(int,void *,class ScriptingExceptionPtr *)
UnityPlayer.dll!SendInputEventsToScript()
UnityPlayer.dll!InputUpdate(enum InputUpdateType)
UnityPlayer.dll!`InternalInitializeModule_Input'::`2'::PreUpdateNewInputUpdateRegistrator::Forward()
UnityPlayer.dll!ExecutePlayerLoop(struct NativePlayerLoopSystem *)
UnityPlayer.dll!ExecutePlayerLoop(struct NativePlayerLoopSystem *)
UnityPlayer.dll!PlayerLoop(void)
UnityPlayer.dll!metro::MainLoop(bool)
UnityPlayer.dll!UnityPlayer::AppCallbacks::smile:oPerformUpdateAndRender(void)
UnityPlayer.dll!UnityPlayer::AppCallbacks::PerformUpdateAndRender(void)
UnityPlayer.dll!UnityPlayer::AppCallbacks::_AppThreadImplementation(void *)
UnityPlayer.dll!UnityPlayer::AppCallbacks::_AppThread(void *)
kernel32.dll!BaseThreadInitThunk()
ntdll.dll!RtlUserThreadStart()```
Thread B (This thread is waiting on a Mutex.)
```Not Flagged 35064 0 Worker Thread SHCore.dll!_WrapperThreadProc UnityPlayer.dll!PlatformMutex::Lock
ntdll.dll!NtWaitForAlertByThreadId()
ntdll.dll!RtlpWaitOnAddressWithTimeout()
ntdll.dll!RtlpWaitOnAddress()
ntdll.dll!RtlpWaitOnCriticalSection()
ntdll.dll!RtlpEnterCriticalSectionContended()
ntdll.dll!RtlEnterCriticalSection()
UnityPlayer.dll!PlatformMutex::Lock(void)
UnityPlayer.dll!Mutex::Lock(void)
UnityPlayer.dll!uwp::ui::TextInputController::OnTextUpdating(struct winrt::Windows::UI::Text::Core::CoreTextTextUpdatingEventArgs const &)
UnityPlayer.dll!winrt::impl::delegate<winrt::Windows::Foundation::TypedEventHandler<winrt::Windows::UI::Text::Core::CoreTextEditContext,winrt::Windows::UI::Text::Core::CoreTextTextUpdatingEventArgs>>::type<<lambda_6e32edd81866d08b092fb0d7968952f0>>::Invoke()
Windows.UI.Core.TextInput.dll!Microsoft::WRL::InvokeTraits<-2>::InvokeDelegates<class <lambda_08d20749b81716ef718bb13b141c8993>,struct Windows::Foundation::ITypedEventHandler<class Windows::UI::ViewManagement::Core::CoreInputView *,class Windows::UI::Internal::ViewManagement::Core::FrameworkInputViewOcclusionsChangedEventArgs *> >(class <lambda_08d20749b81716ef718bb13b141c8993>,class Microsoft::WRL::smile:etails::EventTargetArray *,class Microsoft::WRL::EventSource<struct Windows::Foundation::ITypedEventHandler<class Windows::UI::ViewManagement::Core::CoreInputView *,class Windows::UI::Internal::ViewManagement::Core::FrameworkInputViewOcclusionsChangedEventArgs *>,struct Microsoft::WRL::InvokeModeOptions<-2> > *)
Windows.UI.Core.TextInput.dll!Microsoft::WRL::EventSource<struct Windows::Foundation::ITypedEventHandler<class Windows::UI::ViewManagement::Core::CoreInputView *,class Windows::UI::Internal::ViewManagement::Core::FrameworkInputViewOcclusionsChangedEventArgs *>,struct Microsoft::WRL::InvokeModeOptions<-2> >::smile:oInvoke<class <lambda_08d20749b81716ef718bb13b141c8993> >(class <lambda_08d20749b81716ef718bb13b141c8993>)
Windows.UI.Core.TextInput.dll!Windows::UI::Text::Core::CEditContext::ReplaceTextInternal(int,int,struct MsgString *,bool,int,int)
Windows.UI.Core.TextInput.dll!Windows::UI::Text::Core::CEditContext::ReplaceText(int,int,struct MsgString *)
Windows.UI.Core.TextInput.dll!Windows::UI::Text::Core::CEditContext::InsertText(int,struct MsgString *)
msctf.dll!CTextChange::Execute()
msctf.dll!CTextInputClientOwnerAdapter::_ExecuteOperation()
msctf.dll!CTextInputClientOwnerAdapter::ReplaceText(int,int,struct MsgString *)
TextInputFramework.dll!CTextInputClientOwnerAsync::ReplaceTextInternal(int,int,struct MsgString *,bool,int,int)
TextInputFramework.dll!TextInputClient::ReplaceTextInternal(struct tagMsgRoutingInfo,unsigned int,unsigned int,int,int,struct MsgString *,bool,int,int)
TextInputFramework.dll!TextInputClient::ReplaceText(struct tagMsgRoutingInfo,unsigned int,unsigned int,int,int,struct MsgString *)
TextInputFramework.dll!CTextInputClientFreeThread::ReplaceText()
TextInputFramework.dll!TextInputClientAdapter::ReplaceText(struct tagMsgRoutingInfo,unsigned int,unsigned int,int,int,struct MsgString *)
CoreUIComponents.dll!IRemoteTextInputClient$X__CallbackAdapter::ReplaceTextW(struct Microsoft::CoreUI::MessagingInterop::RoutingInfo,unsigned int,unsigned int,int,int,class System::String *)
CoreUIComponents.dll!IRemoteTextInputClient$X__CallbackAdapter$R::IRemoteTextInputClient_Impl::ReplaceTextW(class System::Object *,struct Microsoft::CoreUI::MessagingInterop::RoutingInfo,unsigned int,unsigned int,int,int,class System::String *)
CoreUIComponents.dll!IRemoteTextInputClient::ReplaceTextW(struct Microsoft::CoreUI::MessagingInterop::RoutingInfo,unsigned int,unsigned int,int,int,class System::String *)
CoreUIComponents.dll!IRemoteTextInputClient$R::Reflection__ReplaceText(void *,void * *,void * *)
CoreUIComponents.dll!Microsoft::CoreUI::Formatting::CnSerializeRead::InvokeMember()
CoreUIComponents.dll!Microsoft::CoreUI::Proxy::ExternalRegisteredObject::Callback_OnMessage()
CoreUIComponents.dll!Microsoft::CoreUI::MessagingInterop::MessageEndpoint$R::smile:elegate1(class System::smile:elegate *,void *,int)
CoreUIComponents.dll!Microsoft__CoreUI__MessagingInterop__EndpointHandler$ExportThunk()
CoreMessaging.dll!Microsoft__CoreUI__ExportEndpointHandler$CallbackThunk(class System::smile:elegate *,void *,int)
CoreMessaging.dll!Microsoft::CoreUI::ExternalEndpoint::Callback_OnMessageCore()
CoreMessaging.dll!Microsoft::CoreUI::Messaging::MessageSessionCommon::Callback_DeliverMessage()
CoreMessaging.dll!Microsoft::CoreUI::Messaging::MessageSessionCommon::Callback_DeliverMessageBatch()
CoreMessaging.dll!Microsoft::CoreUI::Messaging::CrossProcessReceivePort__AlpcReceiveSource::Callback_ProcessBuffer()
CoreMessaging.dll!Microsoft::CoreUI::Messaging::AlpcServerThunk::Callback_ProcessAsynchronousBuffer(struct IAlpcConnection *,void *,unsigned long,void const *,int)
CoreMessaging.dll!AlpcConnection::Callback_DeliverBatchedBuffers()
CoreMessaging.dll!AlpcConnection::HandleSubsequentBufferInBatch()
CoreMessaging.dll!AlpcConnection::Callback_HandleReceivedBuffer()
CoreMessaging.dll!AlpcConnection::Callback_ProcessIncoming()
CoreMessaging.dll!Microsoft::CoreUI::Messaging::CrossProcessReceivePort__AlpcReceiveSource::OnReceive()
CoreMessaging.dll!Microsoft::CoreUI::smile:ispatch::OffThreadReceiver::Callback_OnDispatch()
CoreMessaging.dll!Microsoft::CoreUI::smile:ispatch::EventLoop::Callback_RunCoreLoop()
CoreMessaging.dll!Microsoft::CoreUI::smile:ispatch::UserAdapter::OnUserDispatch()
CoreMessaging.dll!Microsoft::CoreUI::smile:ispatch::UserAdapter_DoWork()
CoreMessaging.dll!Microsoft::CoreUI::smile:ispatch::UserAdapter_WindowProc()
user32.dll!UserCallWinProcCheckWow()
user32.dll!DispatchMessageWorker()
Windows.UI.dll!Windows::UI::Core::CDispatcher::ProcessMessage(bool bDrainQueue, bool * pbWindowMessagesProcessed, bool * pbInvokeItemProcessed) Line 320
Windows.UI.dll!Windows::UI::Core::CDispatcher::WaitAndProcessMessagesInternal(bool bRunAlwaysOnce, void * hEventWait) Line 1950
Windows.UI.dll!Windows::UI::Core::CDispatcher::ProcessEvents(Windows::UI::Core::CoreProcessEventsOption options) Line 596
UnityPlayer.dll!UnityPlayer::AppCallbacks::[UnityPlayer::__IAppCallbacksPublicNonVirtuals]::Run(void)
UnityPlayer.dll!UnityPlayer::AppCallbacks::[UnityPlayer::__IAppCallbacksPublicNonVirtuals]::__abi_UnityPlayer___IAppCallbacksPublicNonVirtuals____abi_Run(void)
inputtestNew.exe!UnityPlayer::__IAppCallbacksPublicNonVirtuals::Run()
inputtestNew.exe!inputtestNew::App::[Windows::ApplicationModel::Core::IFrameworkView]::Run() Line 39
inputtestNew.exe!inputtestNew::App::[Windows::ApplicationModel::Core::IFrameworkView]::__abi_Windows_ApplicationModel_Core_IFrameworkView____abi_Run()
twinapi.appcore.dll!Windows::ApplicationModel::Core::CoreApplicationView::Run()
twinapi.appcore.dll!<lambda>(void)()
SHCore.dll!_WrapperThreadProc()
kernel32.dll!BaseThreadInitThunk()
ntdll.dll!RtlUserThreadStart()```