diff options
author | 2019-06-28 21:51:08 +0200 | |
---|---|---|
committer | 2019-06-29 08:31:35 +0200 | |
commit | 2d4713957af9ad99b53258694837605eab744bc6 (patch) | |
tree | e87a4c8ce5b6ea42bc6f35f2c20ca33203b6f73d /kde-apps | |
parent | dev-ruby/vcr: add 5.0.0 (diff) | |
download | gentoo-2d4713957af9ad99b53258694837605eab744bc6.tar.gz gentoo-2d4713957af9ad99b53258694837605eab744bc6.tar.bz2 gentoo-2d4713957af9ad99b53258694837605eab744bc6.zip |
kde-apps/akonadi: Fix race-condition on akonadi_control start
KDE-Bug: https://bugs.kde.org/show_bug.cgi?id=392092
Package-Manager: Portage-2.3.67, Repoman-2.3.16
Signed-off-by: Andreas Sturmlechner <asturm@gentoo.org>
Diffstat (limited to 'kde-apps')
-rw-r--r-- | kde-apps/akonadi/akonadi-18.12.3-r2.ebuild | 118 | ||||
-rw-r--r-- | kde-apps/akonadi/files/akonadi-18.12.3-akonadi_control-start-race-condition.patch | 187 |
2 files changed, 305 insertions, 0 deletions
diff --git a/kde-apps/akonadi/akonadi-18.12.3-r2.ebuild b/kde-apps/akonadi/akonadi-18.12.3-r2.ebuild new file mode 100644 index 000000000000..cc219d1c8d4a --- /dev/null +++ b/kde-apps/akonadi/akonadi-18.12.3-r2.ebuild @@ -0,0 +1,118 @@ +# Copyright 1999-2019 Gentoo Authors +# Distributed under the terms of the GNU General Public License v2 + +EAPI=7 + +KDE_DESIGNERPLUGIN="true" +KDE_TEST="forceoptional" +VIRTUALDBUS_TEST="true" +VIRTUALX_REQUIRED="test" +inherit kde5 + +DESCRIPTION="Storage service for PIM data and libraries for PIM apps" +HOMEPAGE="https://community.kde.org/KDE_PIM/akonadi" + +KEYWORDS="~amd64 ~arm ~arm64 ~x86" +LICENSE="LGPL-2.1+" +IUSE="+mysql postgres sqlite tools xml" + +REQUIRED_USE="|| ( mysql postgres sqlite ) test? ( tools )" + +COMMON_DEPEND=" + $(add_frameworks_dep kcompletion) + $(add_frameworks_dep kconfig) + $(add_frameworks_dep kconfigwidgets) + $(add_frameworks_dep kcoreaddons) + $(add_frameworks_dep kcrash) + $(add_frameworks_dep kdbusaddons) + $(add_frameworks_dep ki18n) + $(add_frameworks_dep kiconthemes) + $(add_frameworks_dep kio) + $(add_frameworks_dep kitemmodels) + $(add_frameworks_dep kitemviews) + $(add_frameworks_dep kwidgetsaddons) + $(add_frameworks_dep kwindowsystem) + $(add_frameworks_dep kxmlgui) + $(add_qt_dep qtdbus) + $(add_qt_dep qtgui) + $(add_qt_dep qtnetwork) + $(add_qt_dep qtsql 'mysql?,postgres?') + $(add_qt_dep qtwidgets) + $(add_qt_dep qtxml) + sqlite? ( + $(add_qt_dep qtsql 'sqlite' '' '5=') + dev-db/sqlite:3 + ) + xml? ( dev-libs/libxml2 ) +" +DEPEND="${COMMON_DEPEND} + dev-libs/boost + dev-libs/libxslt + test? ( sys-apps/dbus ) +" +RDEPEND="${COMMON_DEPEND} + !kde-apps/akonadi:4 + !<kde-apps/kapptemplate-17.11.80 + !kde-apps/kdepim-l10n + !kde-apps/kdepimlibs + mysql? ( virtual/mysql ) + postgres? ( dev-db/postgresql ) +" + +# some akonadi tests time out, that probably needs more work as it's ~700 tests +RESTRICT+=" test" + +PATCHES=( + "${FILESDIR}/${PN}-18.12.2-mysql56-crash.patch" + "${FILESDIR}/${P}-major-regression-updating-attributes.patch" + "${FILESDIR}/${P}-collection-detach-at-wrong-time-in-attribute.patch" + "${FILESDIR}/${P}-akonadi_control-start-race-condition.patch" +) + +pkg_setup() { + # Set default storage backend in order: MySQL, PostgreSQL, SQLite + # reverse driver check to keep the order + use sqlite && DRIVER="QSQLITE3" + use postgres && DRIVER="QPSQL" + use mysql && DRIVER="QMYSQL" + + if use sqlite || has_version "<${CATEGORY}/${P}[sqlite]"; then + ewarn "We strongly recommend you change your Akonadi database backend to either MySQL" + ewarn "or PostgreSQL in your user configuration." + ewarn "In particular, kde-apps/kmail does not work properly with the sqlite backend." + fi + + kde5_pkg_setup +} + +src_configure() { + local mycmakeargs=( + -DAKONADI_BUILD_QSQLITE=$(usex sqlite) + -DBUILD_TOOLS=$(usex tools) + $(cmake-utils_use_find_package xml LibXml2) + ) + + kde5_src_configure +} + +src_install() { + # Who knows, maybe it accidentally fixes our permission issues + cat <<-EOF > "${T}"/akonadiserverrc +[%General] +Driver=${DRIVER} +EOF + insinto /usr/share/config/akonadi + doins "${T}"/akonadiserverrc + + kde5_src_install +} + +pkg_postinst() { + kde5_pkg_postinst + elog "You can select the storage backend in ~/.config/akonadi/akonadiserverrc." + elog "Available drivers are:" + use mysql && elog " QMYSQL" + use postgres && elog " QPSQL" + use sqlite && elog " QSQLITE3" + elog "${DRIVER} has been set as your default akonadi storage backend." +} 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 new file mode 100644 index 000000000000..dd3aac5f58c3 --- /dev/null +++ b/kde-apps/akonadi/files/akonadi-18.12.3-akonadi_control-start-race-condition.patch @@ -0,0 +1,187 @@ +From c21bb5220a3ae835a5183afd58c186ba21f6c93d Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Daniel=20Vr=C3=A1til?= <dvratil@kde.org> +Date: Fri, 28 Jun 2019 17:10:04 +0200 +Subject: Fix race-condition on akonadi_control start + +Summary: +Check that there are no other akonadi_control instances running as the +very first thing on startup. Previously this check would happen after +AkApplication initialization, which contains some potential race- +conditions, like rotating log files. + +The situation when akonadi_control is launched multiple times can occur +on session startup, when multiple different components will attempt to +launch Akonadi if its not yet running. + +BUG: 392092 +FIXED-IN: 19.04.3 + +Reviewers: #kde_pim, vkrause + +Reviewed By: #kde_pim, vkrause + +Subscribers: kde-pim + +Tags: #kde_pim + +Differential Revision: https://phabricator.kde.org/D22092 +--- + src/akonadicontrol/main.cpp | 16 ++------------- + src/shared/akapplication.cpp | 7 +++---- + src/shared/akapplication.h | 49 ++++++++++++++++++++++++++++++++++++++------ + 3 files changed, 48 insertions(+), 24 deletions(-) + +diff --git a/src/akonadicontrol/main.cpp b/src/akonadicontrol/main.cpp +index 19bebb8..7dba85b 100644 +--- a/src/akonadicontrol/main.cpp ++++ b/src/akonadicontrol/main.cpp +@@ -52,7 +52,7 @@ void crashHandler(int) + + int main(int argc, char **argv) + { +- AkGuiApplication app(argc, argv, AKONADICONTROL_LOG()); ++ AkUniqueGuiApplication app(argc, argv, Akonadi::DBus::serviceName(Akonadi::DBus::ControlLock), AKONADICONTROL_LOG()); + app.setDescription(QStringLiteral("Akonadi Control Process\nDo not run this manually, use 'akonadictl' instead to start/stop Akonadi.")); + + KAboutData aboutData(QStringLiteral("akonadi_control"), +@@ -64,20 +64,8 @@ int main(int argc, char **argv) + + app.parseCommandLine(); + +- // try to acquire the lock first, that means there is no second instance trying to start up at the same time +- // registering the real service name happens in AgentManager::continueStartup(), when everything is in fact up and running +- if (!QDBusConnection::sessionBus().registerService(Akonadi::DBus::serviceName(Akonadi::DBus::ControlLock))) { +- // We couldn't register. Most likely, it's already running. +- const QString lastError = QDBusConnection::sessionBus().lastError().message(); +- if (lastError.isEmpty()) { +- qCWarning(AKONADICONTROL_LOG) << "Unable to register service as" << Akonadi::DBus::serviceName(Akonadi::DBus::ControlLock) << "Maybe it's already running?"; +- } else { +- qCWarning(AKONADICONTROL_LOG) << "Unable to register service as" << Akonadi::DBus::serviceName(Akonadi::DBus::ControlLock) << "Error was:" << lastError; +- } +- return -1; +- } +- + // 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 ++ // TODO: Remove this legacy check? + if (QDBusConnection::sessionBus().interface()->isServiceRegistered(Akonadi::DBus::serviceName(Akonadi::DBus::Control))) { + qCWarning(AKONADICONTROL_LOG) << "Another Akonadi control process is already running."; + return -1; +diff --git a/src/shared/akapplication.cpp b/src/shared/akapplication.cpp +index af860e5..b790b8d 100644 +--- a/src/shared/akapplication.cpp ++++ b/src/shared/akapplication.cpp +@@ -32,10 +32,9 @@ + + AkApplicationBase *AkApplicationBase::sInstance = nullptr; + +-AkApplicationBase::AkApplicationBase(int &argc, char **argv, const QLoggingCategory &loggingCategory) ++AkApplicationBase::AkApplicationBase(std::unique_ptr<QCoreApplication> app, const QLoggingCategory &loggingCategory) + : QObject(nullptr) +- , mArgc(argc) +- , mArgv(argv) ++ , mApp(std::move(app)) + , mLoggingCategory(loggingCategory) + { + Q_ASSERT(!sInstance); +@@ -59,7 +58,7 @@ AkApplicationBase *AkApplicationBase::instance() + + void AkApplicationBase::init() + { +- akInit(QString::fromLatin1(mArgv[0])); ++ akInit(mApp->applicationName()); + akInitRemoteLog(); + + if (!QDBusConnection::sessionBus().isConnected()) { +diff --git a/src/shared/akapplication.h b/src/shared/akapplication.h +index aae7a99..433b725 100644 +--- a/src/shared/akapplication.h ++++ b/src/shared/akapplication.h +@@ -23,6 +23,10 @@ + #include <QObject> + #include <QCommandLineParser> + #include <QLoggingCategory> ++#include <QDBusConnection> ++#include <QDBusError> ++ ++#include <memory> + + class QCoreApplication; + class QApplication; +@@ -55,16 +59,15 @@ public: + int exec(); + + protected: +- AkApplicationBase(int &argc, char **argv, const QLoggingCategory &loggingCategory); ++ AkApplicationBase(std::unique_ptr<QCoreApplication> app, const QLoggingCategory &loggingCategory); + void init(); +- QScopedPointer<QCoreApplication> mApp; ++ ++ std::unique_ptr<QCoreApplication> mApp; + + private Q_SLOTS: + void pollSessionBus() const; + + private: +- int mArgc; +- char **mArgv; + QString mInstanceId; + const QLoggingCategory &mLoggingCategory; + static AkApplicationBase *sInstance; +@@ -77,13 +80,46 @@ class AkApplicationImpl : public AkApplicationBase + { + public: + AkApplicationImpl(int &argc, char **argv, const QLoggingCategory &loggingCategory = *QLoggingCategory::defaultCategory()) +- : AkApplicationBase(argc, argv, loggingCategory) ++ : AkApplicationBase(std::make_unique<T>(argc, argv), loggingCategory) + { +- mApp.reset(new T(argc, argv)); + init(); + } + }; + ++template<typename T> ++class AkUniqueApplicationImpl : public AkApplicationBase ++{ ++public: ++ AkUniqueApplicationImpl(int &argc, char **argv, const QString &serviceName, const QLoggingCategory &loggingCategory = *QLoggingCategory::defaultCategory()) ++ : AkApplicationBase(std::make_unique<T>(argc, argv), loggingCategory) ++ { ++ registerUniqueServiceOrTerminate(serviceName, loggingCategory); ++ init(); ++ } ++ ++private: ++ void registerUniqueServiceOrTerminate(const QString &serviceName, const QLoggingCategory &log) ++ { ++ auto bus = QDBusConnection::sessionBus(); ++ if (!bus.isConnected()) { ++ qCCritical(log, "Session bus not found. Is DBus running?"); ++ exit(1); ++ } ++ ++ if (!bus.registerService(serviceName)) { ++ // We couldn't register. Most likely, it's already running. ++ const QString lastError = bus.lastError().message(); ++ if (lastError.isEmpty()) { ++ qCInfo(log, "Service %s already registered, terminating now.", qUtf8Printable(serviceName)); ++ exit(0); // already running, so it's OK. Terminate now. ++ } else { ++ qCCritical(log, "Unable to register service as %s due to an error: %s", qUtf8Printable(serviceName), qUtf8Printable(lastError)); ++ exit(1); // :( ++ } ++ } ++ } ++}; ++ + /** + * Returns the contents of @p name environment variable if it is defined, + * or @p defaultValue otherwise. +@@ -93,5 +129,6 @@ QString akGetEnv(const char *name, const QString &defaultValue = QString()); + typedef AkApplicationImpl<QCoreApplication> AkCoreApplication; + typedef AkApplicationImpl<QApplication> AkApplication; + typedef AkApplicationImpl<QGuiApplication> AkGuiApplication; ++typedef AkUniqueApplicationImpl<QGuiApplication> AkUniqueGuiApplication; + + #endif +-- +cgit v1.1 |