From 1e7fd6302aa39f1a011e2e4d711bca7a88a62076 Mon Sep 17 00:00:00 2001
From: Andrey Kleshchev <andreykproductengine@lindenlab.com>
Date: Wed, 18 Aug 2021 22:27:19 +0300
Subject: [PATCH] SL-15462 Refactor voiceControlCoro() into a state machine #2

---
 indra/newview/llvoicevivox.cpp | 38 ++++++++++++++++++++++++++++++----
 indra/newview/llvoicevivox.h   |  1 +
 2 files changed, 35 insertions(+), 4 deletions(-)

diff --git a/indra/newview/llvoicevivox.cpp b/indra/newview/llvoicevivox.cpp
index a8d5ef627f9..4aa6f2c6b29 100644
--- a/indra/newview/llvoicevivox.cpp
+++ b/indra/newview/llvoicevivox.cpp
@@ -675,6 +675,30 @@ typedef enum e_voice_control_coro_state
 } EVoiceControlCoroState;
 
 void LLVivoxVoiceClient::voiceControlCoro()
+{
+    int state = 0;
+    try
+    {
+        // state is passed as a reference instead of being
+        // a member due to unresolved issues with coroutine
+        // surviving longer than LLVivoxVoiceClient
+        voiceControlStateMachine(state);
+    }
+    catch (const LLContinueError&)
+    {
+        LOG_UNHANDLED_EXCEPTION("LLVivoxVoiceClient");
+    }
+    catch (...)
+    {
+        // Ideally for Windows need to log SEH exception instead or to set SEH
+        // handlers but bugsplat shows local variables for windows, which should
+        // be enough
+        LL_WARNS("Voice") << "voiceControlStateMachine crashed in state " << state << LL_ENDL;
+        throw;
+    }
+}
+
+void LLVivoxVoiceClient::voiceControlStateMachine(S32 &coro_state)
 {
     LL_DEBUGS("Voice") << "starting" << LL_ENDL;
     mIsCoroutineActive = true;
@@ -682,14 +706,15 @@ void LLVivoxVoiceClient::voiceControlCoro()
 
     U32 retry = 0;
 
-    EVoiceControlCoroState coro_state = VOICE_STATE_TP_WAIT;
+    coro_state = VOICE_STATE_TP_WAIT;
 
     do
     {
         if (sShuttingDown)
         {
-            // Vivox singleton performed the exit, and no longer
-            // cares about state of coroutine, so just stop
+            // Vivox singleton performed the exit, logged out,
+            // cleaned sockets, gateway and no longer cares
+            // about state of coroutine, so just stop
             return;
         }
 
@@ -797,7 +822,7 @@ void LLVivoxVoiceClient::voiceControlCoro()
             break;
 
         case VOICE_STATE_WAIT_FOR_CHANNEL:
-            waitForChannel();
+            waitForChannel(); // todo: split into more states like login/fonts
             coro_state = VOICE_STATE_DISCONNECT;
             break;
 
@@ -1865,6 +1890,11 @@ bool LLVivoxVoiceClient::waitForChannel()
         {
             retrieveVoiceFonts();
 
+            if (sShuttingDown)
+            {
+                return false;
+            }
+
             // Request the set of available voice fonts.
             refreshVoiceEffectLists(false);
         }
diff --git a/indra/newview/llvoicevivox.h b/indra/newview/llvoicevivox.h
index 4ee0545a726..cf30a4e86ac 100644
--- a/indra/newview/llvoicevivox.h
+++ b/indra/newview/llvoicevivox.h
@@ -626,6 +626,7 @@ class LLVivoxVoiceClient :	public LLSingleton<LLVivoxVoiceClient>,
     // Coroutine support methods
     //---
     void voiceControlCoro();
+    void voiceControlStateMachine(S32 &coro_state);
 
     bool endAndDisconnectSession();
 
-- 
GitLab