summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike <contact@mikelittman.me>2026-10-14 00:04:11 -0500
committerGitHub <noreply@github.com>2026-10-14 13:04:11 +0800
commit4d3ec2142c2fcafec17425284a59134f62c3f8b7 (patch)
tree1a167e4b946da44f1ed3888850898b48a0db45fc
parent9cc783022a202a1d00b5dc8eaf01ffddbc9fa39f (diff)
Log out before exiting on the first terminate signal (#35)
SIGTERM was marking the app quitting immediately, so the Mac frame pump stopped before LogoutRequest and the simulator kept the agent in the region. The first signal now runs the normal logout. A second signal still forces the process to exit.
-rw-r--r--indra/llcommon/llapp.cpp30
-rw-r--r--indra/llcommon/llapp.h3
-rw-r--r--indra/newview/llappviewer.cpp8
3 files changed, 35 insertions, 6 deletions
diff --git a/indra/llcommon/llapp.cpp b/indra/llcommon/llapp.cpp
index 02d6da989a..278a8f7c2f 100644
--- a/indra/llcommon/llapp.cpp
+++ b/indra/llcommon/llapp.cpp
@@ -28,6 +28,7 @@
#include "llapp.h"
+#include <csignal>
#include <cstdlib>
#ifdef LL_DARWIN
@@ -397,6 +398,22 @@ void LLApp::writeMiniDump()
{
}
+namespace
+{
+ volatile sig_atomic_t sTermCount = 0;
+}
+
+// static
+bool LLApp::consumeSignalQuit()
+{
+ if (sTermCount == 0)
+ {
+ return false;
+ }
+ sTermCount = 0;
+ return true;
+}
+
// static
void LLApp::setQuitting()
{
@@ -623,18 +640,19 @@ void default_unix_signal_handler(int signum, siginfo_t *info, void *)
{
LL_WARNS() << "Signal handler - Got SIGINT, or TERM, exiting gracefully" << LL_ENDL;
}
- // Graceful exit
- // Just set our state to quitting, not error
- if (LLApp::isQuitting() || LLApp::isError())
+ // The first signal asks the main loop to log out. setQuitting() here
+ // makes the Mac frame pump return immediately, so LogoutRequest is
+ // never sent and the simulator keeps the agent in the region.
+ if (sTermCount > 0 || LLApp::isQuitting() || LLApp::isError())
{
- // We're already trying to die, just ignore this signal
if (LLApp::sLogInSignal)
{
- LL_INFOS() << "Signal handler - Already trying to quit, ignoring signal!" << LL_ENDL;
+ LL_INFOS() << "Signal handler - Already trying to quit, forcing exit" << LL_ENDL;
}
+ LLApp::setQuitting();
return;
}
- LLApp::setQuitting();
+ sTermCount = 1;
return;
case SIGALRM:
case SIGPIPE:
diff --git a/indra/llcommon/llapp.h b/indra/llcommon/llapp.h
index 3a855bc480..590991bbd7 100644
--- a/indra/llcommon/llapp.h
+++ b/indra/llcommon/llapp.h
@@ -195,6 +195,9 @@ public:
// Application status
//
static void setQuitting(); // Set status to QUITTING, the app is now shutting down
+ // True once after SIGTERM or SIGINT. The main loop should log out
+ // before setQuitting(), so the simulator releases the agent.
+ static bool consumeSignalQuit();
static void setStopped(); // Set status to STOPPED, the app is done running and should exit
static void setError(); // Set status to ERROR, the error handler should run
static bool isStopped();
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index d48ccdb9ea..f8c687b0fc 100644
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -1360,6 +1360,14 @@ bool LLAppViewer::frame()
bool LLAppViewer::doFrame()
{
+ // SIGTERM asks for a normal logout. Quitting immediately skips
+ // LogoutRequest and leaves the agent in the region.
+ if (LLApp::consumeSignalQuit() && !mQuitRequested && !isQuitting())
+ {
+ LL_INFOS() << "Terminate signal, logging out before exit" << LL_ENDL;
+ requestQuit();
+ }
+
resumeMainloopTimeout("Main:doFrameStart");
U32 fpsLimitMaxFps = (U32)gSavedSettings.getU32("MaxFPS");