diff --git a/app/streaming/session.cpp b/app/streaming/session.cpp index 947acd3e..c0062ec3 100644 --- a/app/streaming/session.cpp +++ b/app/streaming/session.cpp @@ -35,6 +35,14 @@ #define CONN_TEST_SERVER "qt.conntest.moonlight-stream.org" +// Running the connection process asynchronously seems to reliably +// cause a crash in QSGRenderThread on Wayland and strange crashes +// elsewhere. Until these are figured out, avoid the async connect +// thread on Linux and BSDs. +#if !defined(Q_OS_UNIX) || defined(Q_OS_DARWIN) +#define USE_ASYNC_CONNECT_THREAD 1 +#endif + CONNECTION_LISTENER_CALLBACKS Session::k_ConnCallbacks = { Session::clStageStarting, nullptr, @@ -55,6 +63,11 @@ void Session::clStageStarting(int stage) // which happens to be the main thread, so it's cool to interact // with the GUI in these callbacks. emit s_ActiveSession->stageStarting(QString::fromLocal8Bit(LiGetStageName(stage))); + +#ifndef USE_ASYNC_CONNECT_THREAD + QCoreApplication::processEvents(QEventLoop::ExcludeUserInputEvents); + QCoreApplication::sendPostedEvents(); +#endif } void Session::clStageFailed(int stage, int errorCode) @@ -63,6 +76,11 @@ void Session::clStageFailed(int stage, int errorCode) s_ActiveSession->m_PortTestResults = LiTestClientConnectivity(CONN_TEST_SERVER, 443, LiGetPortFlagsFromStage(stage)); emit s_ActiveSession->stageFailed(QString::fromLocal8Bit(LiGetStageName(stage)), errorCode); + +#ifndef USE_ASYNC_CONNECT_THREAD + QCoreApplication::processEvents(QEventLoop::ExcludeUserInputEvents); + QCoreApplication::sendPostedEvents(); +#endif } void Session::clConnectionTerminated(int errorCode) @@ -938,7 +956,6 @@ public: QThread(nullptr), m_Session(session) {} -private: void run() override { m_Session->m_AsyncConnectionSuccess = m_Session->startConnectionAsync(); @@ -952,7 +969,17 @@ bool Session::startConnectionAsync() { // Wait 1.5 seconds before connecting to let the user // have time to read any messages present on the segue +#ifdef USE_ASYNC_CONNECT_THREAD SDL_Delay(1500); +#else + uint32_t start = SDL_GetTicks(); + while (!SDL_TICKS_PASSED(SDL_GetTicks(), start + 1500)) { + // Pump the UI loop while we wait since we're not async + SDL_Delay(5); + QCoreApplication::processEvents(QEventLoop::ExcludeUserInputEvents); + QCoreApplication::sendPostedEvents(); + } +#endif // The UI should have ensured the old game was already quit // if we decide to stream a different game. @@ -1077,11 +1104,15 @@ void Session::exec(int displayOriginX, int displayOriginY) // Kick off the async connection thread while we sit here and pump the event loop AsyncConnectionStartThread asyncConnThread(this); +#ifdef USE_ASYNC_CONNECT_THREAD asyncConnThread.start(); while (!asyncConnThread.wait(10)) { QCoreApplication::processEvents(QEventLoop::ExcludeUserInputEvents); QCoreApplication::sendPostedEvents(); } +#else + asyncConnThread.run(); +#endif // Pump the event loop one last time to ensure we pick up any events from // the thread that happened while it was in the final successful QThread::wait().