1 |
commit: 2d4713957af9ad99b53258694837605eab744bc6 |
2 |
Author: Andreas Sturmlechner <asturm <AT> gentoo <DOT> org> |
3 |
AuthorDate: Fri Jun 28 19:51:08 2019 +0000 |
4 |
Commit: Andreas Sturmlechner <asturm <AT> gentoo <DOT> org> |
5 |
CommitDate: Sat Jun 29 06:31:35 2019 +0000 |
6 |
URL: https://gitweb.gentoo.org/repo/gentoo.git/commit/?id=2d471395 |
7 |
|
8 |
kde-apps/akonadi: Fix race-condition on akonadi_control start |
9 |
|
10 |
KDE-Bug: https://bugs.kde.org/show_bug.cgi?id=392092 |
11 |
Package-Manager: Portage-2.3.67, Repoman-2.3.16 |
12 |
Signed-off-by: Andreas Sturmlechner <asturm <AT> gentoo.org> |
13 |
|
14 |
kde-apps/akonadi/akonadi-18.12.3-r2.ebuild | 118 +++++++++++++ |
15 |
...12.3-akonadi_control-start-race-condition.patch | 187 +++++++++++++++++++++ |
16 |
2 files changed, 305 insertions(+) |
17 |
|
18 |
diff --git a/kde-apps/akonadi/akonadi-18.12.3-r2.ebuild b/kde-apps/akonadi/akonadi-18.12.3-r2.ebuild |
19 |
new file mode 100644 |
20 |
index 00000000000..cc219d1c8d4 |
21 |
--- /dev/null |
22 |
+++ b/kde-apps/akonadi/akonadi-18.12.3-r2.ebuild |
23 |
@@ -0,0 +1,118 @@ |
24 |
+# Copyright 1999-2019 Gentoo Authors |
25 |
+# Distributed under the terms of the GNU General Public License v2 |
26 |
+ |
27 |
+EAPI=7 |
28 |
+ |
29 |
+KDE_DESIGNERPLUGIN="true" |
30 |
+KDE_TEST="forceoptional" |
31 |
+VIRTUALDBUS_TEST="true" |
32 |
+VIRTUALX_REQUIRED="test" |
33 |
+inherit kde5 |
34 |
+ |
35 |
+DESCRIPTION="Storage service for PIM data and libraries for PIM apps" |
36 |
+HOMEPAGE="https://community.kde.org/KDE_PIM/akonadi" |
37 |
+ |
38 |
+KEYWORDS="~amd64 ~arm ~arm64 ~x86" |
39 |
+LICENSE="LGPL-2.1+" |
40 |
+IUSE="+mysql postgres sqlite tools xml" |
41 |
+ |
42 |
+REQUIRED_USE="|| ( mysql postgres sqlite ) test? ( tools )" |
43 |
+ |
44 |
+COMMON_DEPEND=" |
45 |
+ $(add_frameworks_dep kcompletion) |
46 |
+ $(add_frameworks_dep kconfig) |
47 |
+ $(add_frameworks_dep kconfigwidgets) |
48 |
+ $(add_frameworks_dep kcoreaddons) |
49 |
+ $(add_frameworks_dep kcrash) |
50 |
+ $(add_frameworks_dep kdbusaddons) |
51 |
+ $(add_frameworks_dep ki18n) |
52 |
+ $(add_frameworks_dep kiconthemes) |
53 |
+ $(add_frameworks_dep kio) |
54 |
+ $(add_frameworks_dep kitemmodels) |
55 |
+ $(add_frameworks_dep kitemviews) |
56 |
+ $(add_frameworks_dep kwidgetsaddons) |
57 |
+ $(add_frameworks_dep kwindowsystem) |
58 |
+ $(add_frameworks_dep kxmlgui) |
59 |
+ $(add_qt_dep qtdbus) |
60 |
+ $(add_qt_dep qtgui) |
61 |
+ $(add_qt_dep qtnetwork) |
62 |
+ $(add_qt_dep qtsql 'mysql?,postgres?') |
63 |
+ $(add_qt_dep qtwidgets) |
64 |
+ $(add_qt_dep qtxml) |
65 |
+ sqlite? ( |
66 |
+ $(add_qt_dep qtsql 'sqlite' '' '5=') |
67 |
+ dev-db/sqlite:3 |
68 |
+ ) |
69 |
+ xml? ( dev-libs/libxml2 ) |
70 |
+" |
71 |
+DEPEND="${COMMON_DEPEND} |
72 |
+ dev-libs/boost |
73 |
+ dev-libs/libxslt |
74 |
+ test? ( sys-apps/dbus ) |
75 |
+" |
76 |
+RDEPEND="${COMMON_DEPEND} |
77 |
+ !kde-apps/akonadi:4 |
78 |
+ !<kde-apps/kapptemplate-17.11.80 |
79 |
+ !kde-apps/kdepim-l10n |
80 |
+ !kde-apps/kdepimlibs |
81 |
+ mysql? ( virtual/mysql ) |
82 |
+ postgres? ( dev-db/postgresql ) |
83 |
+" |
84 |
+ |
85 |
+# some akonadi tests time out, that probably needs more work as it's ~700 tests |
86 |
+RESTRICT+=" test" |
87 |
+ |
88 |
+PATCHES=( |
89 |
+ "${FILESDIR}/${PN}-18.12.2-mysql56-crash.patch" |
90 |
+ "${FILESDIR}/${P}-major-regression-updating-attributes.patch" |
91 |
+ "${FILESDIR}/${P}-collection-detach-at-wrong-time-in-attribute.patch" |
92 |
+ "${FILESDIR}/${P}-akonadi_control-start-race-condition.patch" |
93 |
+) |
94 |
+ |
95 |
+pkg_setup() { |
96 |
+ # Set default storage backend in order: MySQL, PostgreSQL, SQLite |
97 |
+ # reverse driver check to keep the order |
98 |
+ use sqlite && DRIVER="QSQLITE3" |
99 |
+ use postgres && DRIVER="QPSQL" |
100 |
+ use mysql && DRIVER="QMYSQL" |
101 |
+ |
102 |
+ if use sqlite || has_version "<${CATEGORY}/${P}[sqlite]"; then |
103 |
+ ewarn "We strongly recommend you change your Akonadi database backend to either MySQL" |
104 |
+ ewarn "or PostgreSQL in your user configuration." |
105 |
+ ewarn "In particular, kde-apps/kmail does not work properly with the sqlite backend." |
106 |
+ fi |
107 |
+ |
108 |
+ kde5_pkg_setup |
109 |
+} |
110 |
+ |
111 |
+src_configure() { |
112 |
+ local mycmakeargs=( |
113 |
+ -DAKONADI_BUILD_QSQLITE=$(usex sqlite) |
114 |
+ -DBUILD_TOOLS=$(usex tools) |
115 |
+ $(cmake-utils_use_find_package xml LibXml2) |
116 |
+ ) |
117 |
+ |
118 |
+ kde5_src_configure |
119 |
+} |
120 |
+ |
121 |
+src_install() { |
122 |
+ # Who knows, maybe it accidentally fixes our permission issues |
123 |
+ cat <<-EOF > "${T}"/akonadiserverrc |
124 |
+[%General] |
125 |
+Driver=${DRIVER} |
126 |
+EOF |
127 |
+ insinto /usr/share/config/akonadi |
128 |
+ doins "${T}"/akonadiserverrc |
129 |
+ |
130 |
+ kde5_src_install |
131 |
+} |
132 |
+ |
133 |
+pkg_postinst() { |
134 |
+ kde5_pkg_postinst |
135 |
+ elog "You can select the storage backend in ~/.config/akonadi/akonadiserverrc." |
136 |
+ elog "Available drivers are:" |
137 |
+ use mysql && elog " QMYSQL" |
138 |
+ use postgres && elog " QPSQL" |
139 |
+ use sqlite && elog " QSQLITE3" |
140 |
+ elog "${DRIVER} has been set as your default akonadi storage backend." |
141 |
+} |
142 |
|
143 |
diff --git a/kde-apps/akonadi/files/akonadi-18.12.3-akonadi_control-start-race-condition.patch b/kde-apps/akonadi/files/akonadi-18.12.3-akonadi_control-start-race-condition.patch |
144 |
new file mode 100644 |
145 |
index 00000000000..dd3aac5f58c |
146 |
--- /dev/null |
147 |
+++ b/kde-apps/akonadi/files/akonadi-18.12.3-akonadi_control-start-race-condition.patch |
148 |
@@ -0,0 +1,187 @@ |
149 |
+From c21bb5220a3ae835a5183afd58c186ba21f6c93d Mon Sep 17 00:00:00 2001 |
150 |
+From: =?UTF-8?q?Daniel=20Vr=C3=A1til?= <dvratil@×××.org> |
151 |
+Date: Fri, 28 Jun 2019 17:10:04 +0200 |
152 |
+Subject: Fix race-condition on akonadi_control start |
153 |
+ |
154 |
+Summary: |
155 |
+Check that there are no other akonadi_control instances running as the |
156 |
+very first thing on startup. Previously this check would happen after |
157 |
+AkApplication initialization, which contains some potential race- |
158 |
+conditions, like rotating log files. |
159 |
+ |
160 |
+The situation when akonadi_control is launched multiple times can occur |
161 |
+on session startup, when multiple different components will attempt to |
162 |
+launch Akonadi if its not yet running. |
163 |
+ |
164 |
+BUG: 392092 |
165 |
+FIXED-IN: 19.04.3 |
166 |
+ |
167 |
+Reviewers: #kde_pim, vkrause |
168 |
+ |
169 |
+Reviewed By: #kde_pim, vkrause |
170 |
+ |
171 |
+Subscribers: kde-pim |
172 |
+ |
173 |
+Tags: #kde_pim |
174 |
+ |
175 |
+Differential Revision: https://phabricator.kde.org/D22092 |
176 |
+--- |
177 |
+ src/akonadicontrol/main.cpp | 16 ++------------- |
178 |
+ src/shared/akapplication.cpp | 7 +++---- |
179 |
+ src/shared/akapplication.h | 49 ++++++++++++++++++++++++++++++++++++++------ |
180 |
+ 3 files changed, 48 insertions(+), 24 deletions(-) |
181 |
+ |
182 |
+diff --git a/src/akonadicontrol/main.cpp b/src/akonadicontrol/main.cpp |
183 |
+index 19bebb8..7dba85b 100644 |
184 |
+--- a/src/akonadicontrol/main.cpp |
185 |
++++ b/src/akonadicontrol/main.cpp |
186 |
+@@ -52,7 +52,7 @@ void crashHandler(int) |
187 |
+ |
188 |
+ int main(int argc, char **argv) |
189 |
+ { |
190 |
+- AkGuiApplication app(argc, argv, AKONADICONTROL_LOG()); |
191 |
++ AkUniqueGuiApplication app(argc, argv, Akonadi::DBus::serviceName(Akonadi::DBus::ControlLock), AKONADICONTROL_LOG()); |
192 |
+ app.setDescription(QStringLiteral("Akonadi Control Process\nDo not run this manually, use 'akonadictl' instead to start/stop Akonadi.")); |
193 |
+ |
194 |
+ KAboutData aboutData(QStringLiteral("akonadi_control"), |
195 |
+@@ -64,20 +64,8 @@ int main(int argc, char **argv) |
196 |
+ |
197 |
+ app.parseCommandLine(); |
198 |
+ |
199 |
+- // try to acquire the lock first, that means there is no second instance trying to start up at the same time |
200 |
+- // registering the real service name happens in AgentManager::continueStartup(), when everything is in fact up and running |
201 |
+- if (!QDBusConnection::sessionBus().registerService(Akonadi::DBus::serviceName(Akonadi::DBus::ControlLock))) { |
202 |
+- // We couldn't register. Most likely, it's already running. |
203 |
+- const QString lastError = QDBusConnection::sessionBus().lastError().message(); |
204 |
+- if (lastError.isEmpty()) { |
205 |
+- qCWarning(AKONADICONTROL_LOG) << "Unable to register service as" << Akonadi::DBus::serviceName(Akonadi::DBus::ControlLock) << "Maybe it's already running?"; |
206 |
+- } else { |
207 |
+- qCWarning(AKONADICONTROL_LOG) << "Unable to register service as" << Akonadi::DBus::serviceName(Akonadi::DBus::ControlLock) << "Error was:" << lastError; |
208 |
+- } |
209 |
+- return -1; |
210 |
+- } |
211 |
+- |
212 |
+ // older Akonadi server versions don't use the lock service yet, so check if one is already running before we try to start another one |
213 |
++ // TODO: Remove this legacy check? |
214 |
+ if (QDBusConnection::sessionBus().interface()->isServiceRegistered(Akonadi::DBus::serviceName(Akonadi::DBus::Control))) { |
215 |
+ qCWarning(AKONADICONTROL_LOG) << "Another Akonadi control process is already running."; |
216 |
+ return -1; |
217 |
+diff --git a/src/shared/akapplication.cpp b/src/shared/akapplication.cpp |
218 |
+index af860e5..b790b8d 100644 |
219 |
+--- a/src/shared/akapplication.cpp |
220 |
++++ b/src/shared/akapplication.cpp |
221 |
+@@ -32,10 +32,9 @@ |
222 |
+ |
223 |
+ AkApplicationBase *AkApplicationBase::sInstance = nullptr; |
224 |
+ |
225 |
+-AkApplicationBase::AkApplicationBase(int &argc, char **argv, const QLoggingCategory &loggingCategory) |
226 |
++AkApplicationBase::AkApplicationBase(std::unique_ptr<QCoreApplication> app, const QLoggingCategory &loggingCategory) |
227 |
+ : QObject(nullptr) |
228 |
+- , mArgc(argc) |
229 |
+- , mArgv(argv) |
230 |
++ , mApp(std::move(app)) |
231 |
+ , mLoggingCategory(loggingCategory) |
232 |
+ { |
233 |
+ Q_ASSERT(!sInstance); |
234 |
+@@ -59,7 +58,7 @@ AkApplicationBase *AkApplicationBase::instance() |
235 |
+ |
236 |
+ void AkApplicationBase::init() |
237 |
+ { |
238 |
+- akInit(QString::fromLatin1(mArgv[0])); |
239 |
++ akInit(mApp->applicationName()); |
240 |
+ akInitRemoteLog(); |
241 |
+ |
242 |
+ if (!QDBusConnection::sessionBus().isConnected()) { |
243 |
+diff --git a/src/shared/akapplication.h b/src/shared/akapplication.h |
244 |
+index aae7a99..433b725 100644 |
245 |
+--- a/src/shared/akapplication.h |
246 |
++++ b/src/shared/akapplication.h |
247 |
+@@ -23,6 +23,10 @@ |
248 |
+ #include <QObject> |
249 |
+ #include <QCommandLineParser> |
250 |
+ #include <QLoggingCategory> |
251 |
++#include <QDBusConnection> |
252 |
++#include <QDBusError> |
253 |
++ |
254 |
++#include <memory> |
255 |
+ |
256 |
+ class QCoreApplication; |
257 |
+ class QApplication; |
258 |
+@@ -55,16 +59,15 @@ public: |
259 |
+ int exec(); |
260 |
+ |
261 |
+ protected: |
262 |
+- AkApplicationBase(int &argc, char **argv, const QLoggingCategory &loggingCategory); |
263 |
++ AkApplicationBase(std::unique_ptr<QCoreApplication> app, const QLoggingCategory &loggingCategory); |
264 |
+ void init(); |
265 |
+- QScopedPointer<QCoreApplication> mApp; |
266 |
++ |
267 |
++ std::unique_ptr<QCoreApplication> mApp; |
268 |
+ |
269 |
+ private Q_SLOTS: |
270 |
+ void pollSessionBus() const; |
271 |
+ |
272 |
+ private: |
273 |
+- int mArgc; |
274 |
+- char **mArgv; |
275 |
+ QString mInstanceId; |
276 |
+ const QLoggingCategory &mLoggingCategory; |
277 |
+ static AkApplicationBase *sInstance; |
278 |
+@@ -77,13 +80,46 @@ class AkApplicationImpl : public AkApplicationBase |
279 |
+ { |
280 |
+ public: |
281 |
+ AkApplicationImpl(int &argc, char **argv, const QLoggingCategory &loggingCategory = *QLoggingCategory::defaultCategory()) |
282 |
+- : AkApplicationBase(argc, argv, loggingCategory) |
283 |
++ : AkApplicationBase(std::make_unique<T>(argc, argv), loggingCategory) |
284 |
+ { |
285 |
+- mApp.reset(new T(argc, argv)); |
286 |
+ init(); |
287 |
+ } |
288 |
+ }; |
289 |
+ |
290 |
++template<typename T> |
291 |
++class AkUniqueApplicationImpl : public AkApplicationBase |
292 |
++{ |
293 |
++public: |
294 |
++ AkUniqueApplicationImpl(int &argc, char **argv, const QString &serviceName, const QLoggingCategory &loggingCategory = *QLoggingCategory::defaultCategory()) |
295 |
++ : AkApplicationBase(std::make_unique<T>(argc, argv), loggingCategory) |
296 |
++ { |
297 |
++ registerUniqueServiceOrTerminate(serviceName, loggingCategory); |
298 |
++ init(); |
299 |
++ } |
300 |
++ |
301 |
++private: |
302 |
++ void registerUniqueServiceOrTerminate(const QString &serviceName, const QLoggingCategory &log) |
303 |
++ { |
304 |
++ auto bus = QDBusConnection::sessionBus(); |
305 |
++ if (!bus.isConnected()) { |
306 |
++ qCCritical(log, "Session bus not found. Is DBus running?"); |
307 |
++ exit(1); |
308 |
++ } |
309 |
++ |
310 |
++ if (!bus.registerService(serviceName)) { |
311 |
++ // We couldn't register. Most likely, it's already running. |
312 |
++ const QString lastError = bus.lastError().message(); |
313 |
++ if (lastError.isEmpty()) { |
314 |
++ qCInfo(log, "Service %s already registered, terminating now.", qUtf8Printable(serviceName)); |
315 |
++ exit(0); // already running, so it's OK. Terminate now. |
316 |
++ } else { |
317 |
++ qCCritical(log, "Unable to register service as %s due to an error: %s", qUtf8Printable(serviceName), qUtf8Printable(lastError)); |
318 |
++ exit(1); // :( |
319 |
++ } |
320 |
++ } |
321 |
++ } |
322 |
++}; |
323 |
++ |
324 |
+ /** |
325 |
+ * Returns the contents of @p name environment variable if it is defined, |
326 |
+ * or @p defaultValue otherwise. |
327 |
+@@ -93,5 +129,6 @@ QString akGetEnv(const char *name, const QString &defaultValue = QString()); |
328 |
+ typedef AkApplicationImpl<QCoreApplication> AkCoreApplication; |
329 |
+ typedef AkApplicationImpl<QApplication> AkApplication; |
330 |
+ typedef AkApplicationImpl<QGuiApplication> AkGuiApplication; |
331 |
++typedef AkUniqueApplicationImpl<QGuiApplication> AkUniqueGuiApplication; |
332 |
+ |
333 |
+ #endif |
334 |
+-- |
335 |
+cgit v1.1 |