Commit 082643dd authored by Johannes Schwab's avatar Johannes Schwab

server: make signal handling more robust

parent 6fa3d1a8
......@@ -23,46 +23,56 @@
#include <QSocketNotifier>
#include <unistd.h>
#include <csignal>
#include <cstring>
#include <cassert>
UnixSignalHandler::UnixSignalHandler() {
if (socketpair(AF_UNIX, SOCK_STREAM, 0, sigFd) != 0) throw IERROR("Can't create sockets");
QSocketNotifier *sigNot = new QSocketNotifier(sigFd[1], QSocketNotifier::Read, this);
connect(sigNot, &QSocketNotifier::activated, this, [this, sigNot](int fd) {
sigNot->setEnabled(false);
int sig;
if (read(fd, &sig, sizeof(sig)) != sizeof(sig)) {
qWarning() << "Can't read signal from socket";
return;
}
qInfo() << "Received signal" << strsignal(sig);
switch (sig) {
case SIGTERM:
case SIGINT:
emit stopRequested();
break;
case SIGUSR1:
emit printInfo();
break;
default:
assert(false);
}
sigNot->setEnabled(true);
if (socketpair(AF_UNIX, SOCK_STREAM, 0, sigCloseGentlyFd) != 0) throw IERROR("Can't create sockets");
if (socketpair(AF_UNIX, SOCK_STREAM, 0, sigPrintInfoFd) != 0) throw IERROR("Can't create sockets");
QSocketNotifier *sigCloseGentlyNot = new QSocketNotifier(sigCloseGentlyFd[1], QSocketNotifier::Read, this);
QSocketNotifier *sigPrintInfoNot = new QSocketNotifier(sigPrintInfoFd[1], QSocketNotifier::Read, this);
connect(sigCloseGentlyNot, &QSocketNotifier::activated, this, [this, sigCloseGentlyNot](int fd) {
assert(fd == sigCloseGentlyFd[1]);
sigCloseGentlyNot->setEnabled(false);
char sig;
read(fd, &sig, 1);
qInfo() << "Closing gently as requested";
emit closeGently();
sigCloseGentlyNot->setEnabled(true);
});
connect(sigPrintInfoNot, &QSocketNotifier::activated, this, [this, sigPrintInfoNot](int fd) {
assert(fd == sigPrintInfoFd[1]);
sigPrintInfoNot->setEnabled(false);
char sig;
read(fd, &sig, 1);
qDebug() << "Print info requested";
emit printInfo();
sigPrintInfoNot->setEnabled(true);
});
struct sigaction siga;
siga.sa_handler = UnixSignalHandler::sigHandler;
siga.sa_handler = UnixSignalHandler::sigCloseGentlyHandler;
sigemptyset(&siga.sa_mask);
siga.sa_flags |= SA_RESTART;
siga.sa_flags = SA_RESTART;
if (sigaction(SIGTERM, &siga, nullptr) != 0) throw IERROR("Can't set signal hanlder");
if (sigaction(SIGINT, &siga, nullptr) != 0) throw IERROR("Can't set signal hanlder");
siga.sa_handler = UnixSignalHandler::sigPrintInfoHandler;
if (sigaction(SIGUSR1, &siga, nullptr) != 0) throw IERROR("Can't set signal hanlder");
signal(SIGHUP, SIG_IGN);
}
void UnixSignalHandler::sigHandler(int sig) {
if (write(sigFd[0], &sig, sizeof(sig)) != sizeof(sig)) qWarning() << "Can't write signal" << strsignal(sig) << "to socket";
void UnixSignalHandler::sigCloseGentlyHandler(int sig) {
Q_UNUSED(sig);
constexpr char a = 1;
write(sigCloseGentlyFd[0], &a, 1);
}
void UnixSignalHandler::sigPrintInfoHandler(int sig) {
Q_UNUSED(sig);
constexpr char a = 1;
write(sigPrintInfoFd[0], &a, 1);
}
int UnixSignalHandler::sigFd[2];
int UnixSignalHandler::sigCloseGentlyFd[2];
int UnixSignalHandler::sigPrintInfoFd[2];
......@@ -25,15 +25,17 @@ class UnixSignalHandler : public QObject {
Q_OBJECT
private:
static int sigFd[2];
static int sigCloseGentlyFd[2];
static int sigPrintInfoFd[2];
static void sigHandler(int sig);
static void sigCloseGentlyHandler(int sig);
static void sigPrintInfoHandler(int sig);
public:
UnixSignalHandler();
signals:
void stopRequested();
void closeGently();
void printInfo();
};
......
......@@ -215,7 +215,7 @@ int main(int argc, char *argv[]) {
UnixSignalHandler sigHandler; //TODO this may throw
TcpServer server(conf.server);
QObject::connect(&sigHandler, &UnixSignalHandler::stopRequested, &server, &TcpServer::onCloseGently);
QObject::connect(&sigHandler, &UnixSignalHandler::closeGently, &server, &TcpServer::onCloseGently);
QObject::connect(&sigHandler, &UnixSignalHandler::printInfo, &server, &TcpServer::onPrintInfo);
for (auto &w : bw) {
QObject::connect(&server, &TcpServer::closed, w.get(), &BackendWorker::onClose);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment