mirror of
https://github.com/LibreELEC/LibreELEC.tv.git
synced 2025-07-24 11:16:51 +00:00
xbmc: handle SIGTERM
In some situations, due to deadlocks or crashes, xbmc fails to exit properly in CApplication::Stop(), so g_powerManager.Reboot() / g_powerManager.Powerdown() never gets called, that's a big no-no for openelec as our users can't shutdown or reboot. There are few addons reported to cause this behaviour: trakkt.tv, watchdog, weather.underground. I've also noticed that sometimes new threads (FileCache ??) get started AFTER CApplication::Stop() is called, delaying shutdown with 1+ minute (2 curl timeoouts?). The problem seems to be in CJobManager::CancelJobs() but I am too lame to understand where, why, and how to fix it. To me, it seems best to let systemd handle it. systemd sends SIGTERM, then waits TimeoutStopSec=xx seconds then sends SIGKILL,s so dont call g_application.Stop() from ApplicationMessenger as it can not be trusted. save the requested exitcode instead (that's required for CEC to switch off the tv) and do it from a simple SIGTERM handler instead. CEC thread has enough time (5 seconds in xbmc.service) to switch of the TV after receiving OnQuit. As a side "effect", now guisettings.xml will ALWAYS be saved, even if shutdown / rebooot is requested externaly (ssh, 3rdparty script).
This commit is contained in:
parent
fd00ad9503
commit
e4a608dc63
@ -0,0 +1,169 @@
|
||||
From dbc86891d089a2a871be5a8663e8a5a9a1cffb53 Mon Sep 17 00:00:00 2001
|
||||
From: Stefan Saraev <stefan@saraev.ca>
|
||||
Date: Thu, 5 Jun 2014 18:50:04 +0300
|
||||
Subject: [PATCH] handle SIGTERM
|
||||
|
||||
In some situations, due to deadlocks or crashes, xbmc fails to exit properly in
|
||||
CApplication::Stop(), so g_powerManager.Reboot() / g_powerManager.Powerdown() never gets
|
||||
called, that's a big no-no for openelec as our users can't shutdown or reboot.
|
||||
There are few addons reported to cause this behaviour: trakkt.tv, watchdog, weather.underground.
|
||||
|
||||
I've also noticed that sometimes new threads (FileCache ??) get started AFTER
|
||||
CApplication::Stop() is called, delaying shutdown with 1+ minute (2 curl timeoouts?).
|
||||
The problem seems to be in CJobManager::CancelJobs() but I am too lame to understand where,
|
||||
why, and how to fix it.
|
||||
|
||||
To me, it seems best to let systemd handle it. systemd sends SIGTERM, then waits
|
||||
TimeoutStopSec=xx seconds then sends SIGKILL,s so dont call g_application.Stop() from
|
||||
ApplicationMessenger as it can not be trusted. save the requested exitcode instead
|
||||
(that's required for CEC to switch off the tv) and do it from a simple SIGTERM handler instead.
|
||||
|
||||
CEC thread has enough time (5 seconds in xbmc.service) to switch of the TV after receiving OnQuit.
|
||||
As a side "effect", now guisettings.xml will ALWAYS be saved, even if shutdown / rebooot
|
||||
is requested externaly (ssh, 3rdparty script).
|
||||
---
|
||||
xbmc/Application.cpp | 10 ++++++++--
|
||||
xbmc/Application.h | 1 +
|
||||
xbmc/ApplicationMessenger.cpp | 6 ++++--
|
||||
xbmc/XBApplicationEx.cpp | 1 +
|
||||
xbmc/XBApplicationEx.h | 1 +
|
||||
xbmc/main/main.cpp | 15 +++++++++++++++
|
||||
6 files changed, 30 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/xbmc/Application.cpp b/xbmc/Application.cpp
|
||||
index 7f1b764..4441969 100644
|
||||
--- a/xbmc/Application.cpp
|
||||
+++ b/xbmc/Application.cpp
|
||||
@@ -3493,11 +3493,18 @@ bool CApplication::Cleanup()
|
||||
}
|
||||
}
|
||||
|
||||
+void CApplication::SetExitCode(int exitCode)
|
||||
+{
|
||||
+ // save it for CEC
|
||||
+ m_ExitCode = exitCode;
|
||||
+ m_ExitCodeSet = true;
|
||||
+}
|
||||
+
|
||||
void CApplication::Stop(int exitCode)
|
||||
{
|
||||
try
|
||||
{
|
||||
- CVariant vExitCode(exitCode);
|
||||
+ CVariant vExitCode(m_ExitCode);
|
||||
CAnnouncementManager::Get().Announce(System, "xbmc", "OnQuit", vExitCode);
|
||||
|
||||
SaveFileState(true);
|
||||
@@ -3521,7 +3528,6 @@ void CApplication::Stop(int exitCode)
|
||||
|
||||
m_bStop = true;
|
||||
m_AppFocused = false;
|
||||
- m_ExitCode = exitCode;
|
||||
CLog::Log(LOGNOTICE, "stop all");
|
||||
|
||||
// cancel any jobs from the jobmanager
|
||||
diff --git a/xbmc/Application.h b/xbmc/Application.h
|
||||
index 2243f15..97fb316 100644
|
||||
--- a/xbmc/Application.h
|
||||
+++ b/xbmc/Application.h
|
||||
@@ -149,6 +149,7 @@ public:
|
||||
void StartPVRManager(bool bOpenPVRWindow = false);
|
||||
void StopPVRManager();
|
||||
bool IsCurrentThread() const;
|
||||
+ void SetExitCode(int exitCode);
|
||||
void Stop(int exitCode);
|
||||
void RestartApp();
|
||||
void UnloadSkin(bool forReload = false);
|
||||
diff --git a/xbmc/ApplicationMessenger.cpp b/xbmc/ApplicationMessenger.cpp
|
||||
index 3524e89..54a15da 100644
|
||||
--- a/xbmc/ApplicationMessenger.cpp
|
||||
+++ b/xbmc/ApplicationMessenger.cpp
|
||||
@@ -259,13 +259,14 @@ void CApplicationMessenger::ProcessMessage(ThreadMessage *pMsg)
|
||||
|
||||
case TMSG_POWERDOWN:
|
||||
{
|
||||
- g_application.Stop(EXITCODE_POWERDOWN);
|
||||
+ g_application.SetExitCode(EXITCODE_POWERDOWN);
|
||||
g_powerManager.Powerdown();
|
||||
}
|
||||
break;
|
||||
|
||||
case TMSG_QUIT:
|
||||
{
|
||||
+ g_application.SetExitCode(EXITCODE_QUIT);
|
||||
g_application.Stop(EXITCODE_QUIT);
|
||||
}
|
||||
break;
|
||||
@@ -287,7 +288,7 @@ void CApplicationMessenger::ProcessMessage(ThreadMessage *pMsg)
|
||||
case TMSG_RESTART:
|
||||
case TMSG_RESET:
|
||||
{
|
||||
- g_application.Stop(EXITCODE_REBOOT);
|
||||
+ g_application.SetExitCode(EXITCODE_REBOOT);
|
||||
g_powerManager.Reboot();
|
||||
}
|
||||
break;
|
||||
@@ -295,6 +296,7 @@ void CApplicationMessenger::ProcessMessage(ThreadMessage *pMsg)
|
||||
case TMSG_RESTARTAPP:
|
||||
{
|
||||
#if defined(TARGET_WINDOWS) || defined(TARGET_LINUX)
|
||||
+ g_application.SetExitCode(EXITCODE_RESTARTAPP);
|
||||
g_application.Stop(EXITCODE_RESTARTAPP);
|
||||
#endif
|
||||
}
|
||||
diff --git a/xbmc/XBApplicationEx.cpp b/xbmc/XBApplicationEx.cpp
|
||||
index ad6a145..6058938 100644
|
||||
--- a/xbmc/XBApplicationEx.cpp
|
||||
+++ b/xbmc/XBApplicationEx.cpp
|
||||
@@ -40,6 +40,7 @@ CXBApplicationEx::CXBApplicationEx()
|
||||
m_bStop = false;
|
||||
m_AppFocused = true;
|
||||
m_ExitCode = EXITCODE_QUIT;
|
||||
+ m_ExitCodeSet = false;
|
||||
m_renderGUI = false;
|
||||
}
|
||||
|
||||
diff --git a/xbmc/XBApplicationEx.h b/xbmc/XBApplicationEx.h
|
||||
index c46cba1..ed3f35f 100644
|
||||
--- a/xbmc/XBApplicationEx.h
|
||||
+++ b/xbmc/XBApplicationEx.h
|
||||
@@ -40,6 +40,7 @@ public:
|
||||
// Variables for timing
|
||||
bool m_bStop;
|
||||
int m_ExitCode;
|
||||
+ bool m_ExitCodeSet;
|
||||
bool m_AppFocused;
|
||||
bool m_renderGUI;
|
||||
|
||||
diff --git a/xbmc/main/main.cpp b/xbmc/main/main.cpp
|
||||
index ec86426..ad8fe6e 100644
|
||||
--- a/xbmc/main/main.cpp
|
||||
+++ b/xbmc/main/main.cpp
|
||||
@@ -40,9 +40,24 @@
|
||||
#include "input/linux/LIRC.h"
|
||||
#endif
|
||||
#include "XbmcContext.h"
|
||||
+#include "Application.h"
|
||||
+
|
||||
+void xbmc_term_handler(int signum)
|
||||
+{
|
||||
+ CLog::Log(LOGINFO, "Received SIGTERM...");
|
||||
+ if (!g_application.m_ExitCodeSet)
|
||||
+ g_application.SetExitCode(EXITCODE_RESTARTAPP);
|
||||
+ g_application.Stop(EXITCODE_RESTARTAPP);
|
||||
+}
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
+ // SIGTERM handler
|
||||
+ struct sigaction action;
|
||||
+ memset(&action, 0, sizeof(struct sigaction));
|
||||
+ action.sa_handler = xbmc_term_handler;
|
||||
+ sigaction(SIGTERM, &action, NULL);
|
||||
+
|
||||
// set up some xbmc specific relationships
|
||||
XBMC::Context context;
|
||||
|
||||
--
|
||||
1.9.1
|
||||
|
@ -0,0 +1,169 @@
|
||||
From d3a6ee05721ca6536b30a4e270d1844acfcb0533 Mon Sep 17 00:00:00 2001
|
||||
From: Stefan Saraev <stefan@saraev.ca>
|
||||
Date: Thu, 5 Jun 2014 18:50:04 +0300
|
||||
Subject: [PATCH] handle SIGTERM
|
||||
|
||||
In some situations, due to deadlocks or crashes, xbmc fails to exit properly in
|
||||
CApplication::Stop(), so g_powerManager.Reboot() / g_powerManager.Powerdown() never gets
|
||||
called, that's a big no-no for openelec as our users can't shutdown or reboot.
|
||||
There are few addons reported to cause this behaviour: trakkt.tv, watchdog, weather.underground.
|
||||
|
||||
I've also noticed that sometimes new threads (FileCache ??) get started AFTER
|
||||
CApplication::Stop() is called, delaying shutdown with 1+ minute (2 curl timeoouts?).
|
||||
The problem seems to be in CJobManager::CancelJobs() but I am too lame to understand where,
|
||||
why, and how to fix it.
|
||||
|
||||
To me, it seems best to let systemd handle it. systemd sends SIGTERM, then waits
|
||||
TimeoutStopSec=xx seconds then sends SIGKILL,s so dont call g_application.Stop() from
|
||||
ApplicationMessenger as it can not be trusted. save the requested exitcode instead
|
||||
(that's required for CEC to switch off the tv) and do it from a simple SIGTERM handler instead.
|
||||
|
||||
CEC thread has enough time (5 seconds in xbmc.service) to switch of the TV after receiving OnQuit.
|
||||
As a side "effect", now guisettings.xml will ALWAYS be saved, even if shutdown / rebooot
|
||||
is requested externaly (ssh, 3rdparty script).
|
||||
---
|
||||
xbmc/Application.cpp | 10 ++++++++--
|
||||
xbmc/Application.h | 1 +
|
||||
xbmc/ApplicationMessenger.cpp | 6 ++++--
|
||||
xbmc/XBApplicationEx.cpp | 1 +
|
||||
xbmc/XBApplicationEx.h | 1 +
|
||||
xbmc/main/main.cpp | 15 +++++++++++++++
|
||||
6 files changed, 30 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/xbmc/Application.cpp b/xbmc/Application.cpp
|
||||
index 9242d53..1b13667 100644
|
||||
--- a/xbmc/Application.cpp
|
||||
+++ b/xbmc/Application.cpp
|
||||
@@ -3509,11 +3509,18 @@ bool CApplication::Cleanup()
|
||||
}
|
||||
}
|
||||
|
||||
+void CApplication::SetExitCode(int exitCode)
|
||||
+{
|
||||
+ // save it for CEC
|
||||
+ m_ExitCode = exitCode;
|
||||
+ m_ExitCodeSet = true;
|
||||
+}
|
||||
+
|
||||
void CApplication::Stop(int exitCode)
|
||||
{
|
||||
try
|
||||
{
|
||||
- CVariant vExitCode(exitCode);
|
||||
+ CVariant vExitCode(m_ExitCode);
|
||||
CAnnouncementManager::Announce(System, "xbmc", "OnQuit", vExitCode);
|
||||
|
||||
SaveFileState(true);
|
||||
@@ -3537,7 +3544,6 @@ void CApplication::Stop(int exitCode)
|
||||
|
||||
m_bStop = true;
|
||||
m_AppFocused = false;
|
||||
- m_ExitCode = exitCode;
|
||||
CLog::Log(LOGNOTICE, "stop all");
|
||||
|
||||
// cancel any jobs from the jobmanager
|
||||
diff --git a/xbmc/Application.h b/xbmc/Application.h
|
||||
index e3a26c5..35656e3 100644
|
||||
--- a/xbmc/Application.h
|
||||
+++ b/xbmc/Application.h
|
||||
@@ -149,6 +149,7 @@ public:
|
||||
void StartPVRManager(bool bOpenPVRWindow = false);
|
||||
void StopPVRManager();
|
||||
bool IsCurrentThread() const;
|
||||
+ void SetExitCode(int exitCode);
|
||||
void Stop(int exitCode);
|
||||
void RestartApp();
|
||||
void UnloadSkin(bool forReload = false);
|
||||
diff --git a/xbmc/ApplicationMessenger.cpp b/xbmc/ApplicationMessenger.cpp
|
||||
index 3524e89..54a15da 100644
|
||||
--- a/xbmc/ApplicationMessenger.cpp
|
||||
+++ b/xbmc/ApplicationMessenger.cpp
|
||||
@@ -259,13 +259,14 @@ void CApplicationMessenger::ProcessMessage(ThreadMessage *pMsg)
|
||||
|
||||
case TMSG_POWERDOWN:
|
||||
{
|
||||
- g_application.Stop(EXITCODE_POWERDOWN);
|
||||
+ g_application.SetExitCode(EXITCODE_POWERDOWN);
|
||||
g_powerManager.Powerdown();
|
||||
}
|
||||
break;
|
||||
|
||||
case TMSG_QUIT:
|
||||
{
|
||||
+ g_application.SetExitCode(EXITCODE_QUIT);
|
||||
g_application.Stop(EXITCODE_QUIT);
|
||||
}
|
||||
break;
|
||||
@@ -287,7 +288,7 @@ void CApplicationMessenger::ProcessMessage(ThreadMessage *pMsg)
|
||||
case TMSG_RESTART:
|
||||
case TMSG_RESET:
|
||||
{
|
||||
- g_application.Stop(EXITCODE_REBOOT);
|
||||
+ g_application.SetExitCode(EXITCODE_REBOOT);
|
||||
g_powerManager.Reboot();
|
||||
}
|
||||
break;
|
||||
@@ -295,6 +296,7 @@ void CApplicationMessenger::ProcessMessage(ThreadMessage *pMsg)
|
||||
case TMSG_RESTARTAPP:
|
||||
{
|
||||
#if defined(TARGET_WINDOWS) || defined(TARGET_LINUX)
|
||||
+ g_application.SetExitCode(EXITCODE_RESTARTAPP);
|
||||
g_application.Stop(EXITCODE_RESTARTAPP);
|
||||
#endif
|
||||
}
|
||||
diff --git a/xbmc/XBApplicationEx.cpp b/xbmc/XBApplicationEx.cpp
|
||||
index ad6a145..6058938 100644
|
||||
--- a/xbmc/XBApplicationEx.cpp
|
||||
+++ b/xbmc/XBApplicationEx.cpp
|
||||
@@ -40,6 +40,7 @@ CXBApplicationEx::CXBApplicationEx()
|
||||
m_bStop = false;
|
||||
m_AppFocused = true;
|
||||
m_ExitCode = EXITCODE_QUIT;
|
||||
+ m_ExitCodeSet = false;
|
||||
m_renderGUI = false;
|
||||
}
|
||||
|
||||
diff --git a/xbmc/XBApplicationEx.h b/xbmc/XBApplicationEx.h
|
||||
index c46cba1..ed3f35f 100644
|
||||
--- a/xbmc/XBApplicationEx.h
|
||||
+++ b/xbmc/XBApplicationEx.h
|
||||
@@ -40,6 +40,7 @@ public:
|
||||
// Variables for timing
|
||||
bool m_bStop;
|
||||
int m_ExitCode;
|
||||
+ bool m_ExitCodeSet;
|
||||
bool m_AppFocused;
|
||||
bool m_renderGUI;
|
||||
|
||||
diff --git a/xbmc/main/main.cpp b/xbmc/main/main.cpp
|
||||
index ec86426..ad8fe6e 100644
|
||||
--- a/xbmc/main/main.cpp
|
||||
+++ b/xbmc/main/main.cpp
|
||||
@@ -40,9 +40,24 @@
|
||||
#include "input/linux/LIRC.h"
|
||||
#endif
|
||||
#include "XbmcContext.h"
|
||||
+#include "Application.h"
|
||||
+
|
||||
+void xbmc_term_handler(int signum)
|
||||
+{
|
||||
+ CLog::Log(LOGINFO, "Received SIGTERM...");
|
||||
+ if (!g_application.m_ExitCodeSet)
|
||||
+ g_application.SetExitCode(EXITCODE_RESTARTAPP);
|
||||
+ g_application.Stop(EXITCODE_RESTARTAPP);
|
||||
+}
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
+ // SIGTERM handler
|
||||
+ struct sigaction action;
|
||||
+ memset(&action, 0, sizeof(struct sigaction));
|
||||
+ action.sa_handler = xbmc_term_handler;
|
||||
+ sigaction(SIGTERM, &action, NULL);
|
||||
+
|
||||
// set up some xbmc specific relationships
|
||||
XBMC::Context context;
|
||||
|
||||
--
|
||||
1.9.1
|
||||
|
Loading…
x
Reference in New Issue
Block a user