Crash when using setText in a callback from async

Started by Nafffen, 14 July 2023, 10:54:25

Nafffen

Hello, it is probably not relevant to tgui but here is my problem
I have a gRPC call in async mode, signIn asks the server and when it responds, signIn executes the given lambda, my idea was to modify tgui objects in my lambda, here m_labelStatus:
    m_labelStatus->setText("Login in...");

    m_gc.m_connectionService.signIn([this](ConnectionService::SignInReturn& signInReturn){
        if (signInReturn.status.ok()) {
            LOG_DEBUG("{}",signInReturn.data->reply.jwt());
        } else {
            LOG_DEBUG("{}: {}",(int)signInReturn.status.error_code(),signInReturn.status.error_message());
            m_labelStatus->setText("Error: "+signInReturn.status.error_message());
        }
    });

However, the program crashes when it comes to the line m_labelStatus->setText("Error: "+signInReturn.status.error_message());Here is the callstack:
ntdll.dll!ntdll!RtlRegisterSecureMemoryCacheCallback (Unknown Source:0)
ntdll.dll!ntdll!memset (Unknown Source:0)
ntdll.dll!ntdll!RtlRegisterSecureMemoryCacheCallback (Unknown Source:0)
ntdll.dll!ntdll!RtlGetCurrentServiceSessionId (Unknown Source:0)
ntdll.dll!ntdll!RtlGetCurrentServiceSessionId (Unknown Source:0)
ntdll.dll!ntdll!RtlFreeHeap (Unknown Source:0)
msvcrt.dll!msvcrt!free (Unknown Source:0)
sfml-graphics-2.dll!FT_Bitmap_Done (Unknown Source:0)
sfml-graphics-2.dll!FT_Done_Glyph (Unknown Source:0)
sfml-graphics-2.dll!sf::Font::loadGlyph(unsigned int, unsigned int, bool, float) const (Unknown Source:0)
sfml-graphics-2.dll!sf::Font::getGlyph(unsigned int, unsigned int, bool, float) const (Unknown Source:0)
sfml-graphics-2.dll!sf::Font::getKerning(unsigned int, unsigned int, unsigned int, bool) const (Unknown Source:0)
tgui.dll!tgui::BackendFontSFML::getKerning(char32_t, char32_t, unsigned int, bool) (Unknown Source:0)
tgui.dll!tgui::BackendText::updateVertices() (Unknown Source:0)
tgui.dll!tgui::BackendText::getSize() (Unknown Source:0)
tgui.dll!tgui::Label::rearrangeText() (Unknown Source:0)
operator()(const struct {...} * const __closure, ConnectionService::SignInReturn & signInReturn) (c:\FactoryCapi\app\src\main\jni\sources\Scenes\SceneLogin.cpp:210)
std::__invoke_impl<void, SceneLogin::trySignIn()::<lambda(ConnectionService::SignInReturn&)>&, ConnectionService::SignInReturn&>(std::__invoke_other, struct {...} &)(struct {...} & __f) (c:\progra~1\mingw64\include\c++\12.3.0\bits\invoke.h:61)
std::__invoke_r<void, SceneLogin::trySignIn()::<lambda(ConnectionService::SignInReturn&)>&, ConnectionService::SignInReturn&>(struct {...} &)(struct {...} & __fn) (c:\progra~1\mingw64\include\c++\12.3.0\bits\invoke.h:111)
std::_Function_handler<void(ConnectionService::SignInReturn&), SceneLogin::trySignIn()::<lambda(ConnectionService::SignInReturn&)> >::_M_invoke(const std::_Any_data &, ConnectionService::SignInReturn &)(const std::_Any_data & __functor,  __args#0) (c:\progra~1\mingw64\include\c++\12.3.0\bits\std_function.h:290)

Do you know why there is this problem ?
Previously I was handling my grpc returns in an external not async function. But it required me to have a dedicated function called once per frame... So now I am trying to directly handle grpc returns when they arrived

texus

Nothing in TGUI or SFML is thread-safe.
Attempting to change text while another thread is rendering will lead to such crashes.

You shouldn't touch TGUI outside the main thread. You could, but then you have to assure that the main thread is blocked temporarily so that it doesn't access TGUI at the same time (which defeats the whole purpose or executing it in a thread).