-
Notifications
You must be signed in to change notification settings - Fork 883
/
kodi-100.10-handle-SIGTERM.patch
170 lines (154 loc) · 5.43 KB
/
kodi-100.10-handle-SIGTERM.patch
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
From d70e7c8826a95852a05ef3de0fea71c8b85accb1 Mon Sep 17 00:00:00 2001
From: Stefan Saraev <stefan@saraev.ca>
Date: Mon, 15 Dec 2014 21:28:54 +0200
Subject: [PATCH 10/12] 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 da6aa6e..b39c906 100644
--- a/xbmc/Application.cpp
+++ b/xbmc/Application.cpp
@@ -2583,12 +2583,19 @@ 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(CVariant::VariantTypeObject);
- vExitCode["exitcode"] = exitCode;
+ vExitCode["exitcode"] = m_ExitCode;
CAnnouncementManager::Get().Announce(System, "xbmc", "OnQuit", vExitCode);
SaveFileState(true);
@@ -2612,7 +2619,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 b4da8f2..b5fdae6 100644
--- a/xbmc/Application.h
+++ b/xbmc/Application.h
@@ -154,6 +154,7 @@ public:
bool StartPVRManager();
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 a46c9be..9bb6804 100644
--- a/xbmc/ApplicationMessenger.cpp
+++ b/xbmc/ApplicationMessenger.cpp
@@ -261,13 +261,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;
@@ -289,7 +290,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;
@@ -297,6 +298,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 87fe2fd..3bfb338 100644
--- a/xbmc/main/main.cpp
+++ b/xbmc/main/main.cpp
@@ -41,9 +41,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;
--
2.1.4