Search Unity

UnityEngine.Input freezes on WSA input text box when typing rapidly or often randomly

Discussion in 'Input System' started by vierling, Mar 15, 2021.

  1. vierling

    vierling

    Joined:
    Jun 30, 2020
    Posts:
    2
    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)

    Not Flagged        36236    0    Worker Thread    UnityPlayer.dll!00007ffa489f525b()    TextInputFramework.dll!CTextInputClientFreeThread::EditControlInfoChanged
    [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::DoPerformUpdateAndRender(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::Details::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> >::DoInvoke<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::Delegate1(class System::Delegate *,void *,int)
    CoreUIComponents.dll!Microsoft__CoreUI__MessagingInterop__EndpointHandler$ExportThunk()
    CoreMessaging.dll!Microsoft__CoreUI__ExportEndpointHandler$CallbackThunk(class System::Delegate *,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::Dispatch::OffThreadReceiver::Callback_OnDispatch()
    CoreMessaging.dll!Microsoft::CoreUI::Dispatch::EventLoop::Callback_RunCoreLoop()
    CoreMessaging.dll!Microsoft::CoreUI::Dispatch::UserAdapter::OnUserDispatch()
    CoreMessaging.dll!Microsoft::CoreUI::Dispatch::UserAdapter_DoWork()
    CoreMessaging.dll!Microsoft::CoreUI::Dispatch::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()
     
  2. timke

    timke

    Joined:
    Nov 30, 2017
    Posts:
    408
    Hey,

    I'm really sorry to hear about this bug, but thank you for reporting it. I'd thought we'd fixed the race-conditions and deadlocks within the CoreTextEditControlContext implementation, but apparently we missed something.

    Do you happen to know if this also repros in 2020+ releases?

    I can start investigating the problem, but please file a Bug Report so we can properly track it.
     
  3. vierling

    vierling

    Joined:
    Jun 30, 2020
    Posts:
    2
  4. timke

    timke

    Joined:
    Nov 30, 2017
    Posts:
    408
    Update on this issue:

    I verified this bug was been fixed but not yet backported to 2019 LTS. It was discovered and fixed internally, and so didn't have an actual ticket assigned to it.

    I have pending 2019 backports for TouchScreenKeyboard and InputField fixes, which does include this fix. Given the severity of the problem for you, I'll expedite the backports as best I can.

    Thank you again for posting this problem, as I didn't realize how serious the bug was; it only rarely occurs for us.