From 317df68d1f25c9bb6dbd528e26189af24986ef64 Mon Sep 17 00:00:00 2001 From: Keith Smith Date: Tue, 8 Sep 2026 09:27:25 -0600 Subject: [PATCH] Fix RDP connect crash on Windows: initialize FreeRDP signal handling Every reference FreeRDP client (X11, Windows, macOS, SDL, Wayland, Android) calls freerdp_handle_signals() once at startup before connecting. OrbitHub never did. On Windows this is the only place that initializes a global CRITICAL_SECTION used internally by freerdp_add_signal_cleanup_handler(), which freerdp_connect() calls automatically. Skipping it leaves that lock zero-initialized -- invalid on Windows, but silently tolerated on POSIX, which is why this never surfaced in Linux testing. The result was a crash (access violation inside EnterCriticalSection) on every RDP connect attempt on Windows. Call it once, guarded, before the first connection. Co-Authored-By: Claude Sonnet 5 --- src/rdp_session_backend.cpp | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) 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."),