Internal
Public Access
Fix RDP host resolution failure on Windows: initialize Winsock
Every RDP connect attempt on Windows failed instantly with ERRCONNECT_DNS_NAME_NOT_FOUND, even for a literal IP address. Root cause: Winsock requires WSAStartup() to be called once by the process before any socket/getaddrinfo call will succeed, and nothing in OrbitHub was calling it (Qt Network isn't used, so Qt never does it either). FreeRDP's own reference Windows client (wf_client.c) pairs WSAStartup with freerdp_handle_signals() in its startup init for exactly this reason. WinPR provides a portable no-op WSAStartup shim on POSIX, so this can be called unconditionally cross-platform alongside the existing signal-handler fix. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
+28
-11
@@ -33,6 +33,7 @@
|
||||
#include <freerdp/scancode.h>
|
||||
#include <freerdp/settings.h>
|
||||
#include <freerdp/utils/signal.h>
|
||||
#include <winpr/winsock.h>
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/synch.h>
|
||||
#include <winpr/user.h>
|
||||
@@ -41,19 +42,35 @@
|
||||
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()
|
||||
// Mirrors wfreerdp_client_global_init() in FreeRDP's own reference Windows
|
||||
// client (client/Windows/wf_client.c): every reference client calls
|
||||
// WSAStartup + freerdp_handle_signals once at startup before connecting.
|
||||
//
|
||||
// WSAStartup: on Windows, sockets (getaddrinfo et al.) fail immediately
|
||||
// with WSANOTINITIALISED until this has been called by *someone* in the
|
||||
// process; OrbitHub never used Qt Network, so nothing else on Windows was
|
||||
// calling it, and every connect failed instantly with
|
||||
// ERRCONNECT_DNS_NAME_NOT_FOUND even for a literal IP address. WinPR
|
||||
// provides a portable no-op WSAStartup shim on POSIX, so this is safe to
|
||||
// call unconditionally cross-platform.
|
||||
//
|
||||
// freerdp_handle_signals: 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() crashed with a
|
||||
// null-pointer dereference inside EnterCriticalSection.
|
||||
//
|
||||
// Guarded so it only ever runs once.
|
||||
void ensureFreeRdpRuntimeInitialized()
|
||||
{
|
||||
static std::once_flag onceFlag;
|
||||
std::call_once(onceFlag, []() {
|
||||
const int rc = freerdp_handle_signals();
|
||||
Q_UNUSED(rc);
|
||||
WSADATA wsaData;
|
||||
const int wsaRc = WSAStartup(0x101, &wsaData);
|
||||
Q_UNUSED(wsaRc);
|
||||
|
||||
const int signalRc = freerdp_handle_signals();
|
||||
Q_UNUSED(signalRc);
|
||||
});
|
||||
}
|
||||
#endif
|
||||
@@ -1493,7 +1510,7 @@ void RdpSessionBackend::workerMain()
|
||||
m_workerRunning.store(false);
|
||||
return;
|
||||
#else
|
||||
ensureFreeRdpSignalHandlersInitialized();
|
||||
ensureFreeRdpRuntimeInitialized();
|
||||
|
||||
freerdp* instance = freerdp_new();
|
||||
if (instance == nullptr) {
|
||||
|
||||
Reference in New Issue
Block a user