From 5ee45bce45dba29dc96669ed134e59fe7184674d Mon Sep 17 00:00:00 2001 From: Samoilenko Yuri Date: Fri, 17 Jan 2014 17:55:04 +0400 Subject: [PATCH] kded_kdeconnect splitted to module and daemon kded_kdeconnect KDEDModule is a very simple daemon manager now, which allow to start/stop/restart real daemon. kdeconnectd is almost unmodified implementation of Daemon class wrapped with main() and QCoreApplication. --- kded/CMakeLists.txt | 25 +++++++-- kded/daemon.cpp | 7 +-- kded/daemon.h | 9 ++-- kded/kdeconnectd.cpp | 56 +++++++++++++++++++ kded/kded.cpp | 124 +++++++++++++++++++++++++++++++++++++++++++ kded/kded.h | 51 ++++++++++++++++++ 6 files changed, 258 insertions(+), 14 deletions(-) create mode 100644 kded/kdeconnectd.cpp create mode 100644 kded/kded.cpp create mode 100644 kded/kded.h diff --git a/kded/CMakeLists.txt b/kded/CMakeLists.txt index 0134af8aa..6c5b2ad35 100644 --- a/kded/CMakeLists.txt +++ b/kded/CMakeLists.txt @@ -28,7 +28,18 @@ set(kded_kdeconnect_SRCS kdebugnamespace.cpp ) -kde4_add_plugin(kded_kdeconnect ${kded_kdeconnect_SRCS}) +kde4_add_executable(kdeconnectd kdeconnectd.cpp ${kded_kdeconnect_SRCS}) + +target_link_libraries(kdeconnectd + ${KDE4_KDECORE_LIBS} + ${KDE4_KDEUI_LIBS} + ${KDE4_KIO_LIBS} + ${QT_QTNETWORK_LIBRARY} + ${QJSON_LIBRARIES} + ${QCA2_LIBRARIES} +) + +kde4_add_plugin(kded_kdeconnect kded.cpp ${kded_kdeconnect_SRCS}) target_link_libraries(kded_kdeconnect ${KDE4_KDECORE_LIBS} @@ -42,19 +53,27 @@ target_link_libraries(kded_kdeconnect include(../macros.cmake) generate_and_install_dbus_interface( - kded_kdeconnect + kdeconnectd daemon.h org.kde.kdeconnect.daemon.xml OPTIONS -a ) generate_and_install_dbus_interface( - kded_kdeconnect + kdeconnectd device.h org.kde.kdeconnect.device.xml OPTIONS -a ) +generate_and_install_dbus_interface( + kded_kdeconnect + kded.h + org.kde.kdeconnect.kded.xml + OPTIONS -a +) + +install(TARGETS kdeconnectd DESTINATION ${LIBEXEC_INSTALL_DIR}) install(TARGETS kded_kdeconnect DESTINATION ${PLUGIN_INSTALL_DIR}) install(FILES kdeconnect.desktop DESTINATION ${SERVICES_INSTALL_DIR}/kded) install(FILES kdeconnect.notifyrc DESTINATION ${DATA_INSTALL_DIR}/kdeconnect) diff --git a/kded/daemon.cpp b/kded/daemon.cpp index 85df7ea1b..dddb9ece2 100644 --- a/kded/daemon.cpp +++ b/kded/daemon.cpp @@ -36,13 +36,8 @@ #include "backends/lan/lanlinkprovider.h" #include "backends/loopback/loopbacklinkprovider.h" -K_PLUGIN_FACTORY(KdeConnectFactory, registerPlugin();) -K_EXPORT_PLUGIN(KdeConnectFactory("kdeconnect", "kdeconnect")) - -Daemon::Daemon(QObject *parent, const QList&) - : KDEDModule(parent) +Daemon::Daemon(QObject *parent) : QObject(parent) { - KSharedConfigPtr config = KSharedConfig::openConfig("kdeconnectrc"); if (!config->group("myself").hasKey("id")) { diff --git a/kded/daemon.h b/kded/daemon.h index 2644dfa0b..686c393c1 100644 --- a/kded/daemon.h +++ b/kded/daemon.h @@ -18,8 +18,8 @@ * along with this program. If not, see . */ -#ifndef DAEMON_H -#define DAEMON_H +#ifndef KDECONNECT_DAEMON_H +#define KDECONNECT_DAEMON_H #include #include @@ -35,13 +35,13 @@ #include "backends/linkprovider.h" class Daemon - : public KDEDModule + : public QObject { Q_OBJECT Q_CLASSINFO("D-Bus Interface", "org.kde.kdeconnect.daemon") public: - Daemon(QObject *parent, const QList&); + Daemon(QObject *parent); ~Daemon(); public Q_SLOTS: @@ -73,7 +73,6 @@ private: // The Initializer object sets things up, and also does cleanup when it goes out of scope QCA::Initializer mQcaInitializer; - }; #endif diff --git a/kded/kdeconnectd.cpp b/kded/kdeconnectd.cpp new file mode 100644 index 000000000..4c5cfe089 --- /dev/null +++ b/kded/kdeconnectd.cpp @@ -0,0 +1,56 @@ + +#include +#include + +#include +#include + +#include "daemon.h" + +static int sigtermfd[2]; +const static char deadbeef = 1; +struct sigaction action; + +void sighandler(int signum) +{ + if( signum == SIGTERM || signum == SIGINT) + { + ssize_t unused = ::write(sigtermfd[0], &deadbeef, sizeof(deadbeef)); + Q_UNUSED(unused); + } +} + +void initializeTermHandlers(QCoreApplication* app) +{ + ::socketpair(AF_UNIX, SOCK_STREAM, 0, sigtermfd); + QSocketNotifier* snTerm = new QSocketNotifier(sigtermfd[1], QSocketNotifier::Read, app); + QObject::connect(snTerm, SIGNAL(activated(int)), app, SLOT(quit())); + + action.sa_handler = sighandler; + sigemptyset(&action.sa_mask); + action.sa_flags = 0; + + sigaction(SIGTERM, &action, NULL); + sigaction(SIGINT, &action, NULL); +} + +int main(int argc, char* argv[]) +{ + QCoreApplication app(argc, argv); + + initializeTermHandlers(&app); + new Daemon(&app); + return app.exec(); +} + + + + + + + + + + + + diff --git a/kded/kded.cpp b/kded/kded.cpp new file mode 100644 index 000000000..60eb2e40d --- /dev/null +++ b/kded/kded.cpp @@ -0,0 +1,124 @@ +/** + * Copyright 2013 Albert Vaca + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License or (at your option) version 3 or any later version + * accepted by the membership of KDE e.V. (or its successor approved + * by the membership of KDE e.V.), which shall act as a proxy + * defined in Section 14 of version 3 of the license. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "kded.h" + +#include +#include + +#include +#include +#include +#include +#include + +#include "kdebugnamespace.h" + +K_PLUGIN_FACTORY(KdeConnectFactory, registerPlugin();) +K_EXPORT_PLUGIN(KdeConnectFactory("kdeconnect", "kdeconnect")) + +Kded::Kded(QObject *parent, const QList&) + : KDEDModule(parent) + , m_daemon(0) +{ + QDBusConnection::sessionBus().registerService("org.kde.kdeconnect"); + QDBusConnection::sessionBus().registerObject("/modules/kdeconnect/kded", this, QDBusConnection::ExportScriptableContents); + start(); + kDebug(kdeconnect_kded()) << "kded_kdeconnect started"; +} + +Kded::~Kded() +{ + QDBusConnection::sessionBus().unregisterObject("/modules/kdeconnect/kded"); + stop(); + kDebug(kdeconnect_kded()) << "kded_kdeconnect stopped"; +} + +bool Kded::start() +{ + if (m_daemon) + { + return true; + } + + const QString daemon = KStandardDirs::locate("exe", "kdeconnectd"); + kDebug(kdeconnect_kded()) << "Starting daemon " << daemon; + m_daemon = new KProcess(this); + connect(m_daemon, SIGNAL(error(QProcess::ProcessError)), this, SLOT(onError(QProcess::ProcessError))); + connect(m_daemon, SIGNAL(finished(int,QProcess::ExitStatus)), this, SLOT(onFinished(int,QProcess::ExitStatus))); + connect(m_daemon, SIGNAL(finished(int,QProcess::ExitStatus)), m_daemon, SLOT(deleteLater())); + + m_daemon->setProgram(daemon); + m_daemon->start(); + if (!m_daemon->waitForStarted(10000)) + { + kError(kdeconnect_kded()) << "Can't start " << daemon; + return false; + } + + kDebug(kdeconnect_kded()) << "Daemon successfuly started"; + return true; +} + +void Kded::stop() +{ + if (m_daemon) + { + m_daemon->terminate(); + if (m_daemon->waitForFinished(10000)) + { + kDebug(kdeconnect_kded()) << "Daemon successfuly stopped"; + } + else + { + m_daemon->kill(); + kWarning(kdeconnect_kded()) << "Daemon killed"; + } + m_daemon = 0; + } +} + +bool Kded::restart() +{ + stop(); + return start(); +} + +void Kded::onError(QProcess::ProcessError errorCode) +{ + kError(kdeconnect_kded()) << "Process error code=" << errorCode; +} + +void Kded::onFinished(int exitCode, QProcess::ExitStatus status) +{ + m_daemon = 0; + + if (status == QProcess::CrashExit) + { + kError(kdeconnect_kded()) << "Process crashed code=" << exitCode; + kWarning(kdeconnect_kded()) << "Restarting in 5 sec..."; + QTimer::singleShot(5000, this, SLOT(start())); + } + else + { + kWarning(kdeconnect_kded()) << "Process finished code=" << exitCode; + } +} + diff --git a/kded/kded.h b/kded/kded.h new file mode 100644 index 000000000..5b5b0a408 --- /dev/null +++ b/kded/kded.h @@ -0,0 +1,51 @@ +/** + * Copyright 2013 Albert Vaca + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License or (at your option) version 3 or any later version + * accepted by the membership of KDE e.V. (or its successor approved + * by the membership of KDE e.V.), which shall act as a proxy + * defined in Section 14 of version 3 of the license. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef KDECONNECT_KDED_H +#define KDECONNECT_KDED_H + +#include +#include + +class Kded + : public KDEDModule +{ + Q_OBJECT + Q_CLASSINFO("D-Bus Interface", "org.kde.kdeconnect.kded") + +public: + Kded(QObject *parent, const QList&); + ~Kded(); + +public Q_SLOTS: + + Q_SCRIPTABLE bool start(); + Q_SCRIPTABLE void stop(); + Q_SCRIPTABLE bool restart(); + +private Q_SLOTS: + void onError(QProcess::ProcessError); + void onFinished(int, QProcess::ExitStatus); + +private: + KProcess* m_daemon; +}; + +#endif