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/scancode.h>
|
||||||
#include <freerdp/settings.h>
|
#include <freerdp/settings.h>
|
||||||
#include <freerdp/utils/signal.h>
|
#include <freerdp/utils/signal.h>
|
||||||
|
#include <winpr/winsock.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>
|
||||||
@@ -41,19 +42,35 @@
|
|||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
#ifdef ORBITHUB_HAS_FREERDP
|
#ifdef ORBITHUB_HAS_FREERDP
|
||||||
// Every reference FreeRDP client (X11, Windows, macOS, SDL, Wayland,
|
// Mirrors wfreerdp_client_global_init() in FreeRDP's own reference Windows
|
||||||
// Android) calls this once at startup before connecting. On Windows it's
|
// client (client/Windows/wf_client.c): every reference client calls
|
||||||
// the only place that initializes a global CRITICAL_SECTION used by
|
// WSAStartup + freerdp_handle_signals once at startup before connecting.
|
||||||
// freerdp_add_signal_cleanup_handler(); skipping it leaves that lock
|
//
|
||||||
// zero-initialized (invalid on Windows, tolerated on POSIX), so the first
|
// WSAStartup: on Windows, sockets (getaddrinfo et al.) fail immediately
|
||||||
// freerdp_connect() crashes with a null-pointer dereference inside
|
// with WSANOTINITIALISED until this has been called by *someone* in the
|
||||||
// EnterCriticalSection. Guarded so it only ever runs once.
|
// process; OrbitHub never used Qt Network, so nothing else on Windows was
|
||||||
void ensureFreeRdpSignalHandlersInitialized()
|
// 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;
|
static std::once_flag onceFlag;
|
||||||
std::call_once(onceFlag, []() {
|
std::call_once(onceFlag, []() {
|
||||||
const int rc = freerdp_handle_signals();
|
WSADATA wsaData;
|
||||||
Q_UNUSED(rc);
|
const int wsaRc = WSAStartup(0x101, &wsaData);
|
||||||
|
Q_UNUSED(wsaRc);
|
||||||
|
|
||||||
|
const int signalRc = freerdp_handle_signals();
|
||||||
|
Q_UNUSED(signalRc);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -1493,7 +1510,7 @@ void RdpSessionBackend::workerMain()
|
|||||||
m_workerRunning.store(false);
|
m_workerRunning.store(false);
|
||||||
return;
|
return;
|
||||||
#else
|
#else
|
||||||
ensureFreeRdpSignalHandlersInitialized();
|
ensureFreeRdpRuntimeInitialized();
|
||||||
|
|
||||||
freerdp* instance = freerdp_new();
|
freerdp* instance = freerdp_new();
|
||||||
if (instance == nullptr) {
|
if (instance == nullptr) {
|
||||||
|
|||||||
Reference in New Issue
Block a user