#include <QTimer>
#include <QDebug>
+#ifdef Q_OS_UNIX
+# include <QSocketNotifier>
+# include <signal.h>
+# include <unistd.h>
+# include <sys/types.h>
+# include <sys/socket.h>
+#endif
+
AniOni::AniOni(int argc, char **argv) :
QObject(), QtService<QCoreApplication>(argc, argv, "LocalMyList Daemon")
{
runUdpClient = false;
runRenameHandler = false;
watchDirectories = false;
- requestFailTimer = 0;
+ requestFailTimer = nullptr;
+#ifdef Q_OS_UNIX
+ setupUnixSignalHandler();
+ signalFdNotifier = nullptr;
+#endif
}
void AniOni::handleUdpClientError()
void AniOni::start()
{
+#ifdef Q_OS_UNIX
+ signalFdNotifier = new QSocketNotifier(signalFd[1], QSocketNotifier::Read, this);
+ connect(signalFdNotifier, SIGNAL(activated(int)), this, SLOT(handleUnixSignal()));
+#endif
+
#if defined(Q_OS_WIN)
QSettings s(QDir::currentPath() + "/anioni.ini", QSettings::IniFormat);
#elif defined(Q_OS_UNIX)
requestFailTimer->start();
}
+#ifdef Q_OS_UNIX
+void AniOni::handleUnixSignal()
+{
+ signalFdNotifier->setEnabled(false);
+ char tmp;
+ auto ignored = ::read(signalFd[1], &tmp, sizeof(tmp));
+ (void)ignored;
+
+ int signal = static_cast<int>(tmp);
+ qInfo("Got signal %d, quitting...", signal);
+ QTimer::singleShot(0, qApp, SLOT(quit()));
+ signalFdNotifier->setEnabled(true);
+}
+#endif
+
void AniOni::loadSettings(QSettings &s)
{
LocalMyList::instance()->loadLocalSettings(s);
logMessage(message, type);
qWarning() << message;
}
+
+#ifdef Q_OS_UNIX
+void AniOni::setupUnixSignalHandler()
+{
+ if (::socketpair(AF_UNIX, SOCK_STREAM, 0, signalFd))
+ qFatal("Couldn't create signal socketpair");
+
+ struct sigaction action;
+ action.sa_handler = &AniOni::unixSignalHandler;
+ sigemptyset(&action.sa_mask);
+ action.sa_flags = 0;
+ action.sa_flags |= SA_RESTART;
+
+ if (sigaction(SIGTERM, &action, NULL) < 0)
+ qFatal("Failed to set SIGTERM handler");
+ if (sigaction(SIGINT, &action, NULL) < 0)
+ qFatal("Failed to set SIGINT handler");
+ if (sigaction(SIGHUP, &action, NULL) < 0)
+ qFatal("Failed to set SIGHUP handler");
+}
+
+void AniOni::unixSignalHandler(int signal)
+{
+ qWarning("handling signal %d", signal);
+ char c = static_cast<char>(signal);
+ auto ignored = ::write(signalFd[0], &c, sizeof(c));
+ (void)ignored;
+}
+
+int AniOni::signalFd[2] = {};
+#endif
#include <QSettings>
class QTimer;
+#ifdef Q_OS_UNIX
+class QSocketNotifier;
+#endif
class AniOni : public QObject, public QtService<QCoreApplication>
{
public:
explicit AniOni(int argc, char **argv);
-signals:
-
-public slots:
-
protected slots:
void handleUdpClientError();
void failRequests();
protected:
void start();
+private slots:
+#ifdef Q_OS_UNIX
+ void handleUnixSignal();
+#endif
+
private:
void loadSettings(QSettings &s);
void log(const QString &message, QtServiceBase::MessageType type);
+#ifdef Q_OS_UNIX
+ static void setupUnixSignalHandler();
+ static void unixSignalHandler(int signal);
+ static int signalFd[2];
+ QSocketNotifier *signalFdNotifier;
+#endif
+
bool runUdpClient;
bool runRenameHandler;
bool watchDirectories;
#include "anioni.h"
-#ifdef Q_OS_UNIX
-# include <signal.h>
-
-void sighandler(int)
-{
- qDebug("Caught signal. Exiting...");
- qApp->quit();
-}
-#endif
-
int main(int argc, char *argv[])
{
AniOni a(argc, argv);
-
-#ifdef Q_OS_UNIX
- struct sigaction action;
- action.sa_handler = sighandler;
- sigemptyset(&action.sa_mask);
- action.sa_flags = 0;
-
- if (sigaction(SIGTERM, &action, NULL) < 0)
- qWarning("Failed to set signal handler");
- if (sigaction(SIGINT, &action, NULL) < 0)
- qWarning("Failed to set signal handler");
- if (sigaction(SIGHUP, &action, NULL) < 0)
- qWarning("Failed to set signal handler");
-#endif
-
return a.exec();
}