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 <noreply@anthropic.com>
This commit is contained in:
2026-09-08 09:27:25 -06:00
co-authored by Claude Sonnet 5
parent fce69b8be9
commit 317df68d1f
+23
View File
@@ -7,6 +7,7 @@
#include <cmath> #include <cmath>
#include <cstring> #include <cstring>
#include <mutex>
#include <new> #include <new>
#include <utility> #include <utility>
@@ -31,12 +32,32 @@
#include <freerdp/locale/keyboard.h> #include <freerdp/locale/keyboard.h>
#include <freerdp/scancode.h> #include <freerdp/scancode.h>
#include <freerdp/settings.h> #include <freerdp/settings.h>
#include <freerdp/utils/signal.h>
#include <winpr/crt.h> #include <winpr/crt.h>
#include <winpr/synch.h> #include <winpr/synch.h>
#include <winpr/user.h> #include <winpr/user.h>
#endif #endif
namespace { 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 kDefaultDesktopWidth = 1280;
constexpr int kDefaultDesktopHeight = 720; constexpr int kDefaultDesktopHeight = 720;
constexpr int kMinDesktopWidth = 640; constexpr int kMinDesktopWidth = 640;
@@ -1472,6 +1493,8 @@ void RdpSessionBackend::workerMain()
m_workerRunning.store(false); m_workerRunning.store(false);
return; return;
#else #else
ensureFreeRdpSignalHandlersInitialized();
freerdp* instance = freerdp_new(); freerdp* instance = freerdp_new();
if (instance == nullptr) { if (instance == nullptr) {
emitConnectionFailureAsync(QStringLiteral("Failed to initialize FreeRDP runtime."), emitConnectionFailureAsync(QStringLiteral("Failed to initialize FreeRDP runtime."),