1 /***************************************************************************
2 * Copyright (C) 2005-2020 by the Quassel Project *
3 * devel@quassel-irc.org *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (at your option) version 3. *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program; if not, write to the *
17 * Free Software Foundation, Inc., *
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
19 ***************************************************************************/
21 #include "posixsignalwatcher.h"
23 #include <sys/resource.h>
24 #include <sys/socket.h>
26 #include <sys/types.h>
33 #include <QSocketNotifier>
35 int PosixSignalWatcher::_sockpair[2];
37 PosixSignalWatcher::PosixSignalWatcher(QObject* parent)
38 : AbstractSignalWatcher{parent}
40 if (::socketpair(AF_UNIX, SOCK_STREAM, 0, _sockpair)) {
41 qWarning() << "Could not setup POSIX signal watcher:" << ::strerror(errno);
45 _notifier = new QSocketNotifier(_sockpair[1], QSocketNotifier::Read, this);
46 connect(_notifier, &QSocketNotifier::activated, this, &PosixSignalWatcher::onNotify);
47 _notifier->setEnabled(true);
49 registerSignal(SIGINT);
50 registerSignal(SIGTERM);
51 registerSignal(SIGHUP);
54 // we only handle crashes ourselves if coredumps are disabled
55 struct rlimit* limit = (rlimit*)malloc(sizeof(struct rlimit));
56 int rc = getrlimit(RLIMIT_CORE, limit);
57 if (rc == -1 || !((long)limit->rlim_cur > 0 || limit->rlim_cur == RLIM_INFINITY)) {
58 registerSignal(SIGABRT);
59 registerSignal(SIGSEGV);
60 registerSignal(SIGBUS);
66 void PosixSignalWatcher::registerSignal(int signal)
68 struct sigaction sigact;
69 sigact.sa_handler = PosixSignalWatcher::signalHandler;
71 sigemptyset(&sigact.sa_mask);
72 sigact.sa_flags |= SA_RESTART;
73 if (sigaction(signal, &sigact, nullptr)) {
74 qWarning() << "Could not register handler for POSIX signal:" << ::strerror(errno);
78 void PosixSignalWatcher::signalHandler(int signal)
80 auto bytes = ::write(_sockpair[0], &signal, sizeof(signal));
84 void PosixSignalWatcher::onNotify(int sockfd)
87 auto bytes = ::read(sockfd, &signal, sizeof(signal));
89 qInfo() << "Caught signal" << signal;
93 emit handleSignal(Action::Reload);
97 emit handleSignal(Action::Terminate);
102 emit handleSignal(Action::HandleCrash);