From bbfffc2d65ab53acd41ee056fdd2a6ea9c2f6a08 Mon Sep 17 00:00:00 2001 From: David Edmundson Date: Mon, 7 Sep 2015 14:04:17 +0200 Subject: [PATCH] Monitor for the clock changes from the kernel At the moment we update the clock when we resume from suspend or from the time KCM. However the signal from the clock KCM isn't very good as it signals just after it requests an NTP update or clock change, not necessarily when that finishes. Also we miss any external NTP updates which might occur at other times throughout the day, such as a big change when we connect to the network This method also avoids needing solid to tell us when we're resuming from suspend, which is deprecated API and also seems slightly slower. BUG: 344870 REVIEW: 125028 --- dataengines/time/timeengine.cpp | 34 +++++++++++++++++++++++++++++++-- 1 file changed, 32 insertions(+), 2 deletions(-) diff --git a/dataengines/time/timeengine.cpp b/dataengines/time/timeengine.cpp index 2fd979220..6eb51420f 100644 --- a/dataengines/time/timeengine.cpp +++ b/dataengines/time/timeengine.cpp @@ -24,10 +24,17 @@ #include #include #include +#include #include #include +#ifdef Q_OS_LINUX +#include +#include +#include +#endif + #include "timesource.h" //timezone is defined in msvc @@ -54,12 +61,35 @@ TimeEngine::~TimeEngine() void TimeEngine::init() { - //QDBusInterface *ktimezoned = new QDBusInterface("org.kde.kded5", "/modules/ktimezoned", "org.kde.KTimeZoned"); QDBusConnection dbus = QDBusConnection::sessionBus(); dbus.connect(QString(), QString(), "org.kde.KTimeZoned", "timeZoneChanged", this, SLOT(tzConfigChanged())); - dbus.connect(QString(), "/org/kde/kcmshell_clock", "org.kde.kcmshell_clock", "clockUpdated", this, SLOT(clockSkewed())); +#ifdef Q_OS_LINUX + //monitor for the system clock being changed + auto timeChangedFd = timerfd_create(CLOCK_REALTIME, O_CLOEXEC | O_NONBLOCK); + itimerspec timespec; + memset(×pec, 0, sizeof(timespec)); //set all timers to 0 seconds, which creates a timer that won't do anything + + int err = timerfd_settime(timeChangedFd, 3, ×pec, 0); //monitor for the time changing + //(flags == TFD_TIMER_ABSTIME | TFD_TIMER_CANCEL_ON_SET). However these are not exposed in glibc so value is hardcoded + if (err) { + qWarning() << "Could not create timer with TFD_TIMER_CANCEL_ON_SET. Clock skews will not be detected. Error:" << qPrintable(strerror(err)); + } + + connect(this, &QObject::destroyed, [timeChangedFd]() { + close(timeChangedFd); + }); + + auto notifier = new QSocketNotifier(timeChangedFd, QSocketNotifier::Read, this); + connect(notifier, &QSocketNotifier::activated, this, [this](int fd) { + uint64_t c; + read(fd, &c, 8); + clockSkewed(); + }); +#else + dbus.connect(QString(), "/org/kde/kcmshell_clock", "org.kde.kcmshell_clock", "clockUpdated", this, SLOT(clockSkewed())); connect( Solid::PowerManagement::notifier(), SIGNAL(resumingFromSuspend()), this , SLOT(clockSkewed()) ); +#endif } void TimeEngine::clockSkewed()