From de3a1d59836496b786ce31e9f2ce77c0c9db545b Mon Sep 17 00:00:00 2001
From: MilhouseVH <milhouseVH.github@nmacleod.com>
Date: Sun, 3 Apr 2022 11:31:07 +0200
Subject: [PATCH] handle SIGTERM

0. CApplication::Stop cant be trusted. (deadlocks crashes and boo)

so, when shutdown/reboot is requested:

1. save an exit code (for CEC...)
2. call CPowerManager::{Reboot,PowerDown}
3. ... then systemd sends TERM and waits xx seconds before sending KILL
4. CApplication::Stop has xx seconds to save guisettings.xml and boo
5. CEC thread has xx seconds to switch off after it received OnQuit
6. addons / pvrmanager / cec / everything else.. are free to deadlock / crash now, we dont care
7. KILL
---
 xbmc/application/Application.cpp              | 24 ++++++++++++++-----
 xbmc/application/Application.h                |  2 ++
 .../powermanagement/LogindUPowerSyscall.cpp   |  2 --
 3 files changed, 20 insertions(+), 8 deletions(-)

--- a/xbmc/application/Application.cpp
+++ b/xbmc/application/Application.cpp
@@ -1459,12 +1459,12 @@ void CApplication::OnApplicationMessage(
   switch (msg)
   {
   case TMSG_POWERDOWN:
-    if (Stop(EXITCODE_POWERDOWN))
+    if (SetExitCode(EXITCODE_POWERDOWN))
       CServiceBroker::GetPowerManager().Powerdown();
     break;
 
   case TMSG_QUIT:
-    Stop(EXITCODE_QUIT);
+    SetExitCode(EXITCODE_QUIT);
     break;
 
   case TMSG_SHUTDOWN:
@@ -1485,12 +1485,13 @@ void CApplication::OnApplicationMessage(
 
   case TMSG_RESTART:
   case TMSG_RESET:
-    if (Stop(EXITCODE_REBOOT))
+    if (SetExitCode(EXITCODE_REBOOT))
       CServiceBroker::GetPowerManager().Reboot();
     break;
 
   case TMSG_RESTARTAPP:
 #if defined(TARGET_WINDOWS) || defined(TARGET_LINUX)
+    SetExitCode(EXITCODE_RESTARTAPP);
     Stop(EXITCODE_RESTARTAPP);
 #endif
     break;
@@ -2086,7 +2087,7 @@ bool CApplication::Stop(int exitCode)
     m_frameMoveGuard.unlock();
 
     CVariant vExitCode(CVariant::VariantTypeObject);
-    vExitCode["exitcode"] = exitCode;
+    vExitCode["exitcode"] = m_ExitCode;
     CServiceBroker::GetAnnouncementManager()->Announce(ANNOUNCEMENT::System, "OnQuit", vExitCode);
 
     // Abort any active screensaver
@@ -2118,7 +2119,6 @@ bool CApplication::Stop(int exitCode)
     // Needs cleaning up
     CServiceBroker::GetAppMessenger()->Stop();
     m_AppFocused = false;
-    m_ExitCode = exitCode;
     CLog::Log(LOGINFO, "Stopping all");
 
     // cancel any jobs from the jobmanager
@@ -2675,6 +2675,18 @@ void CApplication::StopPlaying()
   }
 }
 
+bool CApplication::SetExitCode(int exitCode)
+{
+  if (!m_ExitCodeSet)
+  {
+    CLog::Log(LOGINFO, "Saving exitCode {}", exitCode);
+    // save it for CEC
+    m_ExitCode = exitCode;
+    m_ExitCodeSet = true;
+  }
+  return true;
+}
+
 bool CApplication::OnMessage(CGUIMessage& message)
 {
   switch (message.GetMessage())
@@ -3245,7 +3257,7 @@ void CApplication::ProcessSlow()
   if (CPlatformPosix::TestQuitFlag())
   {
     CLog::Log(LOGINFO, "Quitting due to POSIX signal");
-    CServiceBroker::GetAppMessenger()->PostMsg(TMSG_QUIT);
+    CServiceBroker::GetAppMessenger()->PostMsg(TMSG_RESTARTAPP);
   }
 #endif
 
--- a/xbmc/application/Application.h
+++ b/xbmc/application/Application.h
@@ -113,6 +113,7 @@ public:
   bool CreateGUI();
   bool InitWindow(RESOLUTION res = RES_INVALID);
 
+  bool SetExitCode(int exitCode);
   bool Stop(int exitCode);
   const std::string& CurrentFile();
   CFileItem& CurrentFileItem();
@@ -251,6 +252,7 @@ private:
   unsigned int m_ProcessedExternalCalls = 0;      /*!< counts calls which are processed during one "door open" cycle in FrameMove */
   unsigned int m_ProcessedExternalDecay = 0;      /*!< counts to close door after a few frames of no python activity */
   int m_ExitCode{EXITCODE_QUIT};
+  bool m_ExitCodeSet = false;
   std::shared_ptr<CFileItem> m_itemCurrentFile; //!< Currently playing file
   CEvent m_playerEvent;
 };
--- a/xbmc/platform/linux/powermanagement/LogindUPowerSyscall.cpp
+++ b/xbmc/platform/linux/powermanagement/LogindUPowerSyscall.cpp
@@ -79,8 +79,6 @@ CLogindUPowerSyscall::~CLogindUPowerSysc
 
 bool CLogindUPowerSyscall::Powerdown()
 {
-  // delay shutdown so that the app can close properly
-  InhibitDelayLockShutdown();
   return LogindSetPowerState("PowerOff");
 }
 
