Internal
Public Access
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:
@@ -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."),
|
||||||
|
|||||||
Reference in New Issue
Block a user