mirror of
https://github.com/yuezk/GlobalProtect-openconnect.git
synced 2025-04-02 18:31:50 -04:00
Handle unix signals
This commit is contained in:
parent
7fa8357a1c
commit
704554d3a5
@ -19,11 +19,13 @@ DEFINES += QT_DEPRECATED_WARNINGS
|
|||||||
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
|
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
|
||||||
|
|
||||||
HEADERS += \
|
HEADERS += \
|
||||||
gpservice.h
|
gpservice.h \
|
||||||
|
sigwatch.h
|
||||||
|
|
||||||
SOURCES += \
|
SOURCES += \
|
||||||
gpservice.cpp \
|
gpservice.cpp \
|
||||||
main.cpp
|
main.cpp \
|
||||||
|
sigwatch.cpp
|
||||||
|
|
||||||
DBUS_ADAPTORS += gpservice.xml
|
DBUS_ADAPTORS += gpservice.xml
|
||||||
|
|
||||||
|
@ -61,6 +61,16 @@ GPService::GPService(QObject *parent)
|
|||||||
QObject::connect(openconnect, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished), this, &GPService::onProcessFinished);
|
QObject::connect(openconnect, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished), this, &GPService::onProcessFinished);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GPService::quit()
|
||||||
|
{
|
||||||
|
if (openconnect->state() == QProcess::NotRunning) {
|
||||||
|
exit(0);
|
||||||
|
} else {
|
||||||
|
aboutToQuit = true;
|
||||||
|
openconnect->terminate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void GPService::connect(QString server, QString username, QString passwd)
|
void GPService::connect(QString server, QString username, QString passwd)
|
||||||
{
|
{
|
||||||
if (status() != QProcess::NotRunning) {
|
if (status() != QProcess::NotRunning) {
|
||||||
@ -139,6 +149,10 @@ void GPService::onProcessFinished(int exitCode, QProcess::ExitStatus exitStatus)
|
|||||||
{
|
{
|
||||||
log("Openconnect process exited with code " + QString::number(exitCode) + " and exit status " + QVariant::fromValue(exitStatus).toString());
|
log("Openconnect process exited with code " + QString::number(exitCode) + " and exit status " + QVariant::fromValue(exitStatus).toString());
|
||||||
emit disconnected();
|
emit disconnected();
|
||||||
|
|
||||||
|
if (aboutToQuit) {
|
||||||
|
exit(0);
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
void GPService::log(QString msg)
|
void GPService::log(QString msg)
|
||||||
|
@ -31,6 +31,7 @@ public slots:
|
|||||||
void connect(QString server, QString username, QString passwd);
|
void connect(QString server, QString username, QString passwd);
|
||||||
void disconnect();
|
void disconnect();
|
||||||
int status();
|
int status();
|
||||||
|
void quit();
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void onProcessStarted();
|
void onProcessStarted();
|
||||||
@ -41,6 +42,7 @@ private slots:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
QProcess *openconnect;
|
QProcess *openconnect;
|
||||||
|
bool aboutToQuit = false;
|
||||||
|
|
||||||
void log(QString msg);
|
void log(QString msg);
|
||||||
static QString findBinary();
|
static QString findBinary();
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#include <QtDBus>
|
#include <QtDBus>
|
||||||
#include "gpservice.h"
|
#include "gpservice.h"
|
||||||
#include "singleapplication.h"
|
#include "singleapplication.h"
|
||||||
|
#include "sigwatch.h"
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
@ -12,7 +13,14 @@ int main(int argc, char *argv[])
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
new GPService;
|
GPService service;
|
||||||
|
|
||||||
|
UnixSignalWatcher sigwatch;
|
||||||
|
sigwatch.watchForSignal(SIGINT);
|
||||||
|
sigwatch.watchForSignal(SIGTERM);
|
||||||
|
sigwatch.watchForSignal(SIGQUIT);
|
||||||
|
sigwatch.watchForSignal(SIGHUP);
|
||||||
|
QObject::connect(&sigwatch, SIGNAL(unixSignal(int)), &service, SLOT(quit()));
|
||||||
|
|
||||||
return app.exec();
|
return app.exec();
|
||||||
}
|
}
|
||||||
|
176
GPService/sigwatch.cpp
Normal file
176
GPService/sigwatch.cpp
Normal file
@ -0,0 +1,176 @@
|
|||||||
|
/*
|
||||||
|
* Unix signal watcher for Qt.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2014 Simon Knopp
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <QMap>
|
||||||
|
#include <QSocketNotifier>
|
||||||
|
#include <QDebug>
|
||||||
|
#include "sigwatch.h"
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief The UnixSignalWatcherPrivate class implements the back-end signal
|
||||||
|
* handling for the UnixSignalWatcher.
|
||||||
|
*
|
||||||
|
* \see http://qt-project.org/doc/qt-5.0/qtdoc/unix-signals.html
|
||||||
|
*/
|
||||||
|
class UnixSignalWatcherPrivate : public QObject
|
||||||
|
{
|
||||||
|
UnixSignalWatcher * const q_ptr;
|
||||||
|
Q_DECLARE_PUBLIC(UnixSignalWatcher)
|
||||||
|
|
||||||
|
public:
|
||||||
|
UnixSignalWatcherPrivate(UnixSignalWatcher *q);
|
||||||
|
~UnixSignalWatcherPrivate();
|
||||||
|
|
||||||
|
void watchForSignal(int signal);
|
||||||
|
static void signalHandler(int signal);
|
||||||
|
|
||||||
|
void _q_onNotify(int sockfd);
|
||||||
|
|
||||||
|
private:
|
||||||
|
static int sockpair[2];
|
||||||
|
QSocketNotifier *notifier;
|
||||||
|
QList<int> watchedSignals;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
int UnixSignalWatcherPrivate::sockpair[2];
|
||||||
|
|
||||||
|
UnixSignalWatcherPrivate::UnixSignalWatcherPrivate(UnixSignalWatcher *q) :
|
||||||
|
q_ptr(q)
|
||||||
|
{
|
||||||
|
// Create socket pair
|
||||||
|
if (::socketpair(AF_UNIX, SOCK_STREAM, 0, sockpair)) {
|
||||||
|
qDebug() << "UnixSignalWatcher: socketpair: " << ::strerror(errno);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a notifier for the read end of the pair
|
||||||
|
notifier = new QSocketNotifier(sockpair[1], QSocketNotifier::Read);
|
||||||
|
QObject::connect(notifier, SIGNAL(activated(int)), q, SLOT(_q_onNotify(int)));
|
||||||
|
notifier->setEnabled(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
UnixSignalWatcherPrivate::~UnixSignalWatcherPrivate()
|
||||||
|
{
|
||||||
|
delete notifier;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Registers a handler for the given Unix \a signal. The handler will write to
|
||||||
|
* a socket pair, the other end of which is connected to a QSocketNotifier.
|
||||||
|
* This provides a way to break out of the asynchronous context from which the
|
||||||
|
* signal handler is called and back into the Qt event loop.
|
||||||
|
*/
|
||||||
|
void UnixSignalWatcherPrivate::watchForSignal(int signal)
|
||||||
|
{
|
||||||
|
if (watchedSignals.contains(signal)) {
|
||||||
|
qDebug() << "Already watching for signal" << signal;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Register a sigaction which will write to the socket pair
|
||||||
|
struct sigaction sigact;
|
||||||
|
sigact.sa_handler = UnixSignalWatcherPrivate::signalHandler;
|
||||||
|
sigact.sa_flags = 0;
|
||||||
|
::sigemptyset(&sigact.sa_mask);
|
||||||
|
sigact.sa_flags |= SA_RESTART;
|
||||||
|
if (::sigaction(signal, &sigact, NULL)) {
|
||||||
|
qDebug() << "UnixSignalWatcher: sigaction: " << ::strerror(errno);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
watchedSignals.append(signal);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Called when a Unix \a signal is received. Write to the socket to wake up the
|
||||||
|
* QSocketNotifier.
|
||||||
|
*/
|
||||||
|
void UnixSignalWatcherPrivate::signalHandler(int signal)
|
||||||
|
{
|
||||||
|
ssize_t nBytes = ::write(sockpair[0], &signal, sizeof(signal));
|
||||||
|
Q_UNUSED(nBytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Called when the signal handler has written to the socket pair. Emits the Unix
|
||||||
|
* signal as a Qt signal.
|
||||||
|
*/
|
||||||
|
void UnixSignalWatcherPrivate::_q_onNotify(int sockfd)
|
||||||
|
{
|
||||||
|
Q_Q(UnixSignalWatcher);
|
||||||
|
|
||||||
|
int signal;
|
||||||
|
ssize_t nBytes = ::read(sockfd, &signal, sizeof(signal));
|
||||||
|
Q_UNUSED(nBytes);
|
||||||
|
qDebug() << "Caught signal:" << ::strsignal(signal);
|
||||||
|
emit q->unixSignal(signal);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Create a new UnixSignalWatcher as a child of the given \a parent.
|
||||||
|
*/
|
||||||
|
UnixSignalWatcher::UnixSignalWatcher(QObject *parent) :
|
||||||
|
QObject(parent),
|
||||||
|
d_ptr(new UnixSignalWatcherPrivate(this))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Destroy this UnixSignalWatcher.
|
||||||
|
*/
|
||||||
|
UnixSignalWatcher::~UnixSignalWatcher()
|
||||||
|
{
|
||||||
|
delete d_ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Register a signal handler for the given \a signal.
|
||||||
|
*
|
||||||
|
* After calling this method you can \c connect() to the unixSignal() Qt signal
|
||||||
|
* to be notified when the Unix signal is received.
|
||||||
|
*/
|
||||||
|
void UnixSignalWatcher::watchForSignal(int signal)
|
||||||
|
{
|
||||||
|
Q_D(UnixSignalWatcher);
|
||||||
|
d->watchForSignal(signal);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \fn void UnixSignalWatcher::unixSignal(int signal)
|
||||||
|
* Emitted when the given Unix \a signal is received.
|
||||||
|
*
|
||||||
|
* watchForSignal() must be called for each Unix signal that you want to receive
|
||||||
|
* via the unixSignal() Qt signal. If a watcher is watching multiple signals,
|
||||||
|
* unixSignal() will be emitted whenever *any* of the watched Unix signals are
|
||||||
|
* received, and the \a signal argument can be inspected to find out which one
|
||||||
|
* was actually received.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "moc_sigwatch.cpp"
|
59
GPService/sigwatch.h
Normal file
59
GPService/sigwatch.h
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
/*
|
||||||
|
* Unix signal watcher for Qt.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2014 Simon Knopp
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SIGWATCH_H
|
||||||
|
#define SIGWATCH_H
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
#include <signal.h>
|
||||||
|
|
||||||
|
class UnixSignalWatcherPrivate;
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief The UnixSignalWatcher class converts Unix signals to Qt signals.
|
||||||
|
*
|
||||||
|
* To watch for a given signal, e.g. \c SIGINT, call \c watchForSignal(SIGINT)
|
||||||
|
* and \c connect() your handler to unixSignal().
|
||||||
|
*/
|
||||||
|
|
||||||
|
class UnixSignalWatcher : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
explicit UnixSignalWatcher(QObject *parent = 0);
|
||||||
|
~UnixSignalWatcher();
|
||||||
|
|
||||||
|
void watchForSignal(int signal);
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void unixSignal(int signal);
|
||||||
|
|
||||||
|
private:
|
||||||
|
UnixSignalWatcherPrivate * const d_ptr;
|
||||||
|
Q_DECLARE_PRIVATE(UnixSignalWatcher)
|
||||||
|
Q_PRIVATE_SLOT(d_func(), void _q_onNotify(int))
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // SIGWATCH_H
|
Loading…
Reference in New Issue
Block a user