graceful shutdown and error handling
- Daemon: async-signal-safe SIGTERM/SIGINT via socketpair - Tray: survives daemon restart, watches for service appear/disappear - KRunner: skips matches if daemon unreachable - Kate: shows error message if daemon not running or session creation fails
This commit is contained in:
parent
db9e7c2830
commit
f9e902a2ad
|
|
@ -1,15 +1,22 @@
|
|||
#include <QCoreApplication>
|
||||
#include <QDBusConnection>
|
||||
#include <QDebug>
|
||||
#include <QSocketNotifier>
|
||||
|
||||
#include <csignal>
|
||||
#include <sys/socket.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "session_manager.h"
|
||||
#include "sessionmanageradaptor.h" // generated by qt6_add_dbus_adaptor
|
||||
|
||||
static void signalHandler(int sig)
|
||||
// Async-signal-safe shutdown via socketpair
|
||||
static int sigFd[2];
|
||||
|
||||
static void signalHandler(int)
|
||||
{
|
||||
qDebug() << "Received signal" << sig << "- shutting down";
|
||||
QCoreApplication::quit();
|
||||
char c = 1;
|
||||
write(sigFd[0], &c, 1);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
|
|
@ -18,7 +25,20 @@ int main(int argc, char *argv[])
|
|||
app.setApplicationName("ollie-kde");
|
||||
app.setOrganizationName("ollie");
|
||||
|
||||
// Handle SIGTERM/SIGINT gracefully
|
||||
// Set up signal handling via socketpair (async-signal-safe)
|
||||
if (socketpair(AF_UNIX, SOCK_STREAM, 0, sigFd) != 0) {
|
||||
qCritical() << "Cannot create signal socketpair";
|
||||
return 1;
|
||||
}
|
||||
|
||||
auto *sigNotifier = new QSocketNotifier(sigFd[1], QSocketNotifier::Read, &app);
|
||||
QObject::connect(sigNotifier, &QSocketNotifier::activated, &app, [&]() {
|
||||
char c;
|
||||
read(sigFd[1], &c, 1);
|
||||
qDebug() << "Received shutdown signal, exiting gracefully...";
|
||||
app.quit();
|
||||
});
|
||||
|
||||
signal(SIGTERM, signalHandler);
|
||||
signal(SIGINT, signalHandler);
|
||||
|
||||
|
|
@ -49,5 +69,8 @@ int main(int argc, char *argv[])
|
|||
|
||||
qDebug() << "ollie-kde daemon started on D-Bus: org.ollie.SessionManager";
|
||||
|
||||
return app.exec();
|
||||
int rc = app.exec();
|
||||
|
||||
qDebug() << "ollie-kde daemon exiting";
|
||||
return rc;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -265,6 +265,8 @@ void OllieKateView::newSession()
|
|||
m_chatOffset = 0;
|
||||
m_sessionLabel->setText("○ " + m_sessionId.left(14) + " [idle]");
|
||||
m_cwdLabel->setText(cwd);
|
||||
} else {
|
||||
m_chatView->setPlainText("Error creating session: " + reply.error().message());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -273,6 +275,10 @@ void OllieKateView::newSession()
|
|||
void OllieKateView::ensureSession()
|
||||
{
|
||||
if (!m_sessionId.isEmpty()) return;
|
||||
if (!m_iface->isValid()) {
|
||||
m_chatView->setPlainText("Error: ollie-kde daemon not running.\nStart with: ollie-kde or rc-service --user ollie-kde start");
|
||||
return;
|
||||
}
|
||||
newSession();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -38,6 +38,11 @@ void OllieRunner::match(KRunner::RunnerContext &context)
|
|||
return;
|
||||
}
|
||||
|
||||
// Bail if daemon isn't running
|
||||
if (!m_iface->isValid()) {
|
||||
return;
|
||||
}
|
||||
|
||||
QString args = query.mid(6).trimmed(); // everything after "ollie "
|
||||
|
||||
if (args.isEmpty() || args == QLatin1String("list")) {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
#include <QApplication>
|
||||
#include <QDBusConnection>
|
||||
#include <QDBusConnectionInterface>
|
||||
#include <QDBusServiceWatcher>
|
||||
#include <QDebug>
|
||||
|
||||
#include "ollie_tray.h"
|
||||
|
|
@ -12,20 +13,36 @@ int main(int argc, char *argv[])
|
|||
app.setOrganizationName("ollie");
|
||||
app.setQuitOnLastWindowClosed(false);
|
||||
|
||||
// Verify the daemon is reachable
|
||||
QDBusConnection bus = QDBusConnection::sessionBus();
|
||||
if (!bus.isConnected()) {
|
||||
qCritical() << "Cannot connect to D-Bus session bus";
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!bus.interface()->isServiceRegistered("org.ollie.SessionManager")) {
|
||||
qCritical() << "ollie-kde daemon not running (org.ollie.SessionManager not registered)";
|
||||
return 1;
|
||||
}
|
||||
|
||||
OllieTray tray;
|
||||
qDebug() << "ollie-tray started";
|
||||
|
||||
// Watch for daemon appearing/disappearing
|
||||
auto *watcher = new QDBusServiceWatcher(
|
||||
"org.ollie.SessionManager",
|
||||
bus,
|
||||
QDBusServiceWatcher::WatchForRegistration | QDBusServiceWatcher::WatchForUnregistration,
|
||||
&app);
|
||||
|
||||
QObject::connect(watcher, &QDBusServiceWatcher::serviceRegistered, [&]() {
|
||||
qDebug() << "Daemon appeared on D-Bus";
|
||||
tray.updateStatus();
|
||||
});
|
||||
|
||||
QObject::connect(watcher, &QDBusServiceWatcher::serviceUnregistered, [&]() {
|
||||
qDebug() << "Daemon disappeared from D-Bus";
|
||||
tray.updateStatus();
|
||||
});
|
||||
|
||||
if (bus.interface()->isServiceRegistered("org.ollie.SessionManager")) {
|
||||
qDebug() << "ollie-tray started (daemon running)";
|
||||
} else {
|
||||
qDebug() << "ollie-tray started (waiting for daemon)";
|
||||
}
|
||||
|
||||
return app.exec();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,6 +15,8 @@ public:
|
|||
explicit OllieTray(QObject *parent = nullptr);
|
||||
~OllieTray() override;
|
||||
|
||||
void updateStatus();
|
||||
|
||||
private slots:
|
||||
void onSessionCreated(const QString &session_id);
|
||||
void onSessionKilled(const QString &session_id);
|
||||
|
|
@ -27,7 +29,6 @@ private slots:
|
|||
|
||||
private:
|
||||
void setupMenu();
|
||||
void updateStatus();
|
||||
void updateTooltip();
|
||||
QStringList callListSessions();
|
||||
bool callKillSession(const QString &id);
|
||||
|
|
|
|||
Reference in New Issue