Skip to content

Commit

Permalink
[host] app: fix app state race in lgmpTimer thread
Browse files Browse the repository at this point in the history
While resuming from hibernation lgmpTimer may transition app.state to
APP_STATE_REINIT_LGMP. Sometimes the transition is lost if the app_main
processing loop also changes app.state simultaneously. This seems to
occur frequently with the hibernation use case.

Separate lgmp timer state into its own enum. Move resulting app.state
transitions to the app_main loop so they are serialized.
  • Loading branch information
aiberia committed Dec 20, 2024
1 parent e25492a commit b9b3109
Showing 1 changed file with 26 additions and 11 deletions.
37 changes: 26 additions & 11 deletions host/src/app.c
Original file line number Diff line number Diff line change
Expand Up @@ -69,10 +69,16 @@ enum AppState
APP_STATE_RUNNING,
APP_STATE_IDLE,
APP_STATE_TRANSITION_TO_IDLE,
APP_STATE_REINIT_LGMP,
APP_STATE_SHUTDOWN
};

enum LGMPTimerState
{
LGMP_TIMER_STATE_OK,
LGMP_TIMER_STATE_CORRUPTED,
LGMP_TIMER_STATE_FAULTED
};

struct app
{
int exitcode;
Expand Down Expand Up @@ -105,7 +111,8 @@ struct app
CaptureInterface * iface;
bool captureStarted;

enum AppState state, lastState;
enum AppState state;
enum LGMPTimerState lgmpTimerState;
LGTimer * lgmpTimer;
LGThread * frameThread;
bool threadsStarted;
Expand Down Expand Up @@ -162,8 +169,7 @@ inline static void setAppState(enum AppState state)
{
if (app.state == APP_STATE_SHUTDOWN)
return;
app.lastState = app.state;
app.state = state;
app.state = state;
}

static bool lgmpTimer(void * opaque)
Expand All @@ -176,12 +182,12 @@ static bool lgmpTimer(void * opaque)
{
DEBUG_ERROR("LGMP reported the shared memory has been corrrupted, "
"attempting to recover");
setAppState(APP_STATE_REINIT_LGMP);
atomic_store(&app.lgmpTimerState, LGMP_TIMER_STATE_CORRUPTED);
return false;
}

DEBUG_ERROR("lgmpHostProcess Failed: %s", lgmpStatusString(status));
setAppState(APP_STATE_SHUTDOWN);
atomic_store(&app.lgmpTimerState, LGMP_TIMER_STATE_FAULTED);
return false;
}

Expand Down Expand Up @@ -785,6 +791,7 @@ static bool lgmpSetup(struct IVSHMEM * shmDev)
app.frameBuffer[i] = (FrameBuffer *)(((uint8_t*)app.frame[i]) + alignOffset);
}

atomic_store(&app.lgmpTimerState, LGMP_TIMER_STATE_OK);
if (!lgCreateTimer(10, lgmpTimer, NULL, &app.lgmpTimer))
{
DEBUG_ERROR("Failed to create the LGMP timer");
Expand All @@ -811,8 +818,7 @@ int app_main(int argc, char * argv[])
// make sure rng is actually seeded for LGMP
srand((unsigned)time(NULL));

app.lastState = APP_STATE_RUNNING;
app.state = APP_STATE_RUNNING;
app.state = APP_STATE_RUNNING;
ivshmemOptionsInit();

// register capture interface options
Expand Down Expand Up @@ -954,16 +960,25 @@ int app_main(int argc, char * argv[])

do
{
switch(app.state)
switch(atomic_load(&app.lgmpTimerState))
{
case APP_STATE_REINIT_LGMP:
case LGMP_TIMER_STATE_OK:
break;

case LGMP_TIMER_STATE_CORRUPTED:
DEBUG_INFO("Performing LGMP reinitialization");
lgmpShutdown();
setAppState(app.lastState);
if (!lgmpSetup(&shmDev))
goto fail_lgmp;
break;

case LGMP_TIMER_STATE_FAULTED:
setAppState(APP_STATE_SHUTDOWN);
break;
}

switch(app.state)
{
case APP_STATE_IDLE:
// if there are no clients subscribed, just remain idle
if (!lgmpHostQueueHasSubs(app.pointerQueue) &&
Expand Down

0 comments on commit b9b3109

Please sign in to comment.