From 7a255aa9c51ebb41bb629f6d327560dcfa18433f Mon Sep 17 00:00:00 2001 From: Joel Holdsworth Date: Sun, 31 Mar 2013 10:31:51 +0100 Subject: [PATCH] Integrated signal handler from qpdfview --- CMakeLists.txt | 2 + main.cpp | 37 ++++++++----------- signalhandler.cpp | 94 +++++++++++++++++++++++++++++++++++++++++++++++ signalhandler.h | 54 +++++++++++++++++++++++++++ 4 files changed, 165 insertions(+), 22 deletions(-) create mode 100644 signalhandler.cpp create mode 100644 signalhandler.h diff --git a/CMakeLists.txt b/CMakeLists.txt index fc8fb4c9..2b9f39d1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -90,6 +90,7 @@ configure_file ( set(pulseview_SOURCES main.cpp + signalhandler.cpp pv/mainwindow.cpp pv/sigsession.cpp pv/data/analog.cpp @@ -119,6 +120,7 @@ set(pulseview_SOURCES ) set(pulseview_HEADERS + signalhandler.h pv/mainwindow.h pv/sigsession.h pv/dialogs/about.h diff --git a/main.cpp b/main.cpp index fef53247..3fcfcc77 100644 --- a/main.cpp +++ b/main.cpp @@ -19,7 +19,6 @@ */ #include /* First, so we avoid a _POSIX_C_SOURCE warning. */ -#include #include #include @@ -28,13 +27,11 @@ #include #include +#include "signalhandler.h" #include "pv/mainwindow.h" #include "config.h" -// Global pointer to our QApplication -QApplication *g_app = NULL; - void usage() { fprintf(stdout, @@ -48,31 +45,13 @@ void usage() "\n", PV_BIN_NAME, PV_DESCRIPTION); } -/* - * SIGINT handler (likely received Ctrl-C from terminal) - */ -void sigint_handler(int param) -{ - (void)param; - - qDebug("Received SIGINT."); - - if (g_app) - g_app->quit(); -} - int main(int argc, char *argv[]) { int ret = 0; struct sr_context *sr_ctx = NULL; const char *open_file = NULL; - // Register a SIGINT handler - signal(SIGINT, sigint_handler); - QApplication a(argc, argv); - // Now we have an application to populate our global pointer - g_app = &a; // Set some application metadata QApplication::setApplicationVersion(PV_VERSION_STRING); @@ -148,6 +127,20 @@ int main(int argc, char *argv[]) pv::MainWindow w(open_file); w.show(); + if(SignalHandler::prepareSignals()) { + SignalHandler *const signalHandler = + new SignalHandler(&w); + QObject::connect(signalHandler, + SIGNAL(sigIntReceived()), + &w, SLOT(close())); + QObject::connect(signalHandler, + SIGNAL(sigTermReceived()), + &w, SLOT(close())); + } else { + qWarning() << + "Could not prepare signal handler."; + } + // Run the application ret = a.exec(); } diff --git a/signalhandler.cpp b/signalhandler.cpp new file mode 100644 index 00000000..a3ef6b82 --- /dev/null +++ b/signalhandler.cpp @@ -0,0 +1,94 @@ +/* + +Copyright 2013 Adam Reichold + +This file is part of qpdfview. + +qpdfview 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) any later version. + +qpdfview 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 qpdfview. If not, see . + +*/ + +#include "signalhandler.h" + +#include +#include +#include + +#include + +int SignalHandler::s_sockets[2]; + +bool SignalHandler::prepareSignals() +{ + if(socketpair(AF_UNIX, SOCK_STREAM, 0, s_sockets) != 0) + { + return false; + } + + struct sigaction sigAction; + + sigAction.sa_handler = SignalHandler::handleSignals; + sigemptyset(&sigAction.sa_mask); + sigAction.sa_flags = SA_RESTART; + + if(sigaction(SIGINT, &sigAction, 0) != 0) + { + close(s_sockets[0]); + close(s_sockets[1]); + + return false; + } + + if(sigaction(SIGTERM, &sigAction, 0) != 0) + { + close(s_sockets[0]); + close(s_sockets[1]); + + return false; + } + + return true; +} + +SignalHandler::SignalHandler(QObject* parent) : QObject(parent), + m_socketNotifier(0) +{ + m_socketNotifier = new QSocketNotifier(s_sockets[1], QSocketNotifier::Read, this); + connect(m_socketNotifier, SIGNAL(activated(int)), SLOT(on_socketNotifier_activated())); +} + +void SignalHandler::on_socketNotifier_activated() +{ + m_socketNotifier->setEnabled(false); + + int sigNumber; + read(s_sockets[1], &sigNumber, sizeof(int)); + + switch(sigNumber) + { + case SIGINT: + emit sigIntReceived(); + break; + case SIGTERM: + emit sigTermReceived(); + break; + } + + m_socketNotifier->setEnabled(true); +} + +void SignalHandler::handleSignals(int sigNumber) +{ + write(s_sockets[0], &sigNumber, sizeof(int)); +} diff --git a/signalhandler.h b/signalhandler.h new file mode 100644 index 00000000..48017629 --- /dev/null +++ b/signalhandler.h @@ -0,0 +1,54 @@ +/* + +Copyright 2013 Adam Reichold + +This file is part of qpdfview. + +qpdfview 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) any later version. + +qpdfview 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 qpdfview. If not, see . + +*/ + +#ifndef SIGNALHANDLER_H +#define SIGNALHANDLER_H + +#include + +class QSocketNotifier; + +class SignalHandler : public QObject +{ + Q_OBJECT + +public: + static bool prepareSignals(); + + explicit SignalHandler(QObject* parent = 0); + +signals: + void sigIntReceived(); + void sigTermReceived(); + +private slots: + void on_socketNotifier_activated(); + +private: + static int s_sockets[2]; + + static void handleSignals(int sigNumber); + + QSocketNotifier* m_socketNotifier; + +}; + +#endif // SIGNALHANDLER_H -- 2.30.2