diff --git a/src/rdp_session_backend.cpp b/src/rdp_session_backend.cpp index 44b7822..59cc854 100644 --- a/src/rdp_session_backend.cpp +++ b/src/rdp_session_backend.cpp @@ -7,6 +7,7 @@ #include #include +#include #include #include @@ -31,12 +32,32 @@ #include #include #include +#include #include #include #include #endif namespace { + +#ifdef ORBITHUB_HAS_FREERDP +// Every reference FreeRDP client (X11, Windows, macOS, SDL, Wayland, +// Android) calls this once at startup before connecting. On Windows it's +// the only place that initializes a global CRITICAL_SECTION used by +// freerdp_add_signal_cleanup_handler(); skipping it leaves that lock +// zero-initialized (invalid on Windows, tolerated on POSIX), so the first +// freerdp_connect() crashes with a null-pointer dereference inside +// EnterCriticalSection. Guarded so it only ever runs once. +void ensureFreeRdpSignalHandlersInitialized() +{ + static std::once_flag onceFlag; + std::call_once(onceFlag, []() { + const int rc = freerdp_handle_signals(); + Q_UNUSED(rc); + }); +} +#endif + constexpr int kDefaultDesktopWidth = 1280; constexpr int kDefaultDesktopHeight = 720; constexpr int kMinDesktopWidth = 640; @@ -1472,6 +1493,8 @@ void RdpSessionBackend::workerMain() m_workerRunning.store(false); return; #else + ensureFreeRdpSignalHandlersInitialized(); + freerdp* instance = freerdp_new(); if (instance == nullptr) { emitConnectionFailureAsync(QStringLiteral("Failed to initialize FreeRDP runtime."),