mirror of
https://github.com/gnif/LookingGlass.git
synced 2026-08-22 15:11:31 +00:00
[client] main: preserve restart after primary video loss
Primary frame and pointer workers can still be unwinding an abandoned payload when another thread detects that the primary transport has disconnected. Their fatal paths previously stored SHUTDOWN unconditionally, allowing a stale renderer or transport failure to overwrite RESTART and terminate the client instead of activating the SPICE fallback. Publish RESTART at the beginning of primary-loss handling, before transport bookkeeping, and make worker-local fatal paths transition to SHUTDOWN only while the application is still RUNNING. Global failures and the case where both primary and fallback sessions are lost remain terminal.
This commit is contained in:
@@ -146,6 +146,14 @@ static bool videoStatusRetry(LG_TransportStatus status,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void primaryWorkerFailed(void)
|
||||||
|
{
|
||||||
|
/* A worker can still be handling an abandoned primary payload after the
|
||||||
|
* session thread has initiated a restart. Preserve that restart so the
|
||||||
|
* fallback video source can take over instead of terminating the client. */
|
||||||
|
app_transitionState(APP_STATE_RUNNING, APP_STATE_SHUTDOWN);
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef ENABLE_TESTS
|
#ifdef ENABLE_TESTS
|
||||||
static struct
|
static struct
|
||||||
{
|
{
|
||||||
@@ -1212,7 +1220,7 @@ int main_cursorThread(void * unused)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
DEBUG_ERROR("Pointer transport failed with status %d", status);
|
DEBUG_ERROR("Pointer transport failed with status %d", status);
|
||||||
app_setState(APP_STATE_SHUTDOWN);
|
primaryWorkerFailed();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -1414,11 +1422,11 @@ int main_frameThread(void * unused)
|
|||||||
primaryLost();
|
primaryLost();
|
||||||
}
|
}
|
||||||
else if (status == LG_TRANSPORT_END)
|
else if (status == LG_TRANSPORT_END)
|
||||||
app_setState(APP_STATE_SHUTDOWN);
|
primaryWorkerFailed();
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
DEBUG_ERROR("Frame transport failed with status %d", status);
|
DEBUG_ERROR("Frame transport failed with status %d", status);
|
||||||
app_setState(APP_STATE_SHUTDOWN);
|
primaryWorkerFailed();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -1443,7 +1451,7 @@ int main_frameThread(void * unused)
|
|||||||
videoPayloadRelease();
|
videoPayloadRelease();
|
||||||
DEBUG_ERROR("Transport returned a frame without format metadata");
|
DEBUG_ERROR("Transport returned a frame without format metadata");
|
||||||
g_state.videoOps->frame->releaseFrame(g_state.transport.handle, &frame);
|
g_state.videoOps->frame->releaseFrame(g_state.transport.handle, &frame);
|
||||||
app_setState(APP_STATE_SHUTDOWN);
|
primaryWorkerFailed();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
const bool formatChanged = sourceChanged ||
|
const bool formatChanged = sourceChanged ||
|
||||||
@@ -1528,7 +1536,7 @@ int main_frameThread(void * unused)
|
|||||||
DEBUG_ERROR("Unsupported frame type");
|
DEBUG_ERROR("Unsupported frame type");
|
||||||
g_state.videoOps->frame->releaseFrame(
|
g_state.videoOps->frame->releaseFrame(
|
||||||
g_state.transport.handle, &frame);
|
g_state.transport.handle, &frame);
|
||||||
app_setState(APP_STATE_SHUTDOWN);
|
primaryWorkerFailed();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1549,7 +1557,7 @@ int main_frameThread(void * unused)
|
|||||||
DEBUG_ERROR("Renderer failed to configure format");
|
DEBUG_ERROR("Renderer failed to configure format");
|
||||||
g_state.videoOps->frame->releaseFrame(
|
g_state.videoOps->frame->releaseFrame(
|
||||||
g_state.transport.handle, &frame);
|
g_state.transport.handle, &frame);
|
||||||
app_setState(APP_STATE_SHUTDOWN);
|
primaryWorkerFailed();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
rendererSupportsNativeHDR = !rendererFormat.hdr ||
|
rendererSupportsNativeHDR = !rendererFormat.hdr ||
|
||||||
@@ -1601,7 +1609,7 @@ int main_frameThread(void * unused)
|
|||||||
frameTimingCancel(frameToken);
|
frameTimingCancel(frameToken);
|
||||||
g_state.videoOps->frame->releaseFrame(g_state.transport.handle, &frame);
|
g_state.videoOps->frame->releaseFrame(g_state.transport.handle, &frame);
|
||||||
DEBUG_ERROR("Renderer onFrame returned failure");
|
DEBUG_ERROR("Renderer onFrame returned failure");
|
||||||
app_setState(APP_STATE_SHUTDOWN);
|
primaryWorkerFailed();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
/* A DMA snapshot can complete on the render thread immediately after it
|
/* A DMA snapshot can complete on the render thread immediately after it
|
||||||
@@ -2628,6 +2636,10 @@ static const LG_TransportFallbackEventOps fallbackEvents =
|
|||||||
|
|
||||||
static void primaryLost(void)
|
static void primaryLost(void)
|
||||||
{
|
{
|
||||||
|
/* Establish restart before updating the transport bookkeeping. Primary
|
||||||
|
* workers may still be unwinding abandoned payloads in parallel and must
|
||||||
|
* observe that their failures no longer warrant a terminal shutdown. */
|
||||||
|
app_setState(APP_STATE_RESTART);
|
||||||
atomic_store_explicit(
|
atomic_store_explicit(
|
||||||
&g_state.lgHostConnected, false, memory_order_release);
|
&g_state.lgHostConnected, false, memory_order_release);
|
||||||
unsigned int lost = atomic_load_explicit(
|
unsigned int lost = atomic_load_explicit(
|
||||||
@@ -2652,7 +2664,6 @@ static void primaryLost(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
DEBUG_INFO("Waiting for the host to restart...");
|
DEBUG_INFO("Waiting for the host to restart...");
|
||||||
app_setState(APP_STATE_RESTART);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool fallbackStart(const uint8_t primaryUUID[16])
|
static bool fallbackStart(const uint8_t primaryUUID[16])
|
||||||
|
|||||||
Reference in New Issue
Block a user