1 /***************************************************************************
2 * Copyright (C) 2005-2019 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/socket.h>
24 #include <sys/types.h>
26 #include <sys/resource.h>
33 #include <QSocketNotifier>
35 #include "logmessage.h"
37 int PosixSignalWatcher::_sockpair[2];
39 PosixSignalWatcher::PosixSignalWatcher(QObject *parent)
40 : AbstractSignalWatcher{parent}
42 if (::socketpair(AF_UNIX, SOCK_STREAM, 0, _sockpair)) {
43 qWarning() << "Could not setup POSIX signal watcher:" << ::strerror(errno);
47 _notifier = new QSocketNotifier(_sockpair[1], QSocketNotifier::Read, this);
48 connect(_notifier, SIGNAL(activated(int)), this, SLOT(onNotify(int)));
49 _notifier->setEnabled(true);
51 registerSignal(SIGINT);
52 registerSignal(SIGTERM);
53 registerSignal(SIGHUP);
56 // we only handle crashes ourselves if coredumps are disabled
57 struct rlimit *limit = (rlimit *)malloc(sizeof(struct rlimit));
58 int rc = getrlimit(RLIMIT_CORE, limit);
59 if (rc == -1 || !((long)limit->rlim_cur > 0 || limit->rlim_cur == RLIM_INFINITY)) {
60 registerSignal(SIGABRT);
61 registerSignal(SIGSEGV);
62 registerSignal(SIGBUS);
68 void PosixSignalWatcher::registerSignal(int signal)
70 struct sigaction sigact;
71 sigact.sa_handler = PosixSignalWatcher::signalHandler;
73 sigemptyset(&sigact.sa_mask);
74 sigact.sa_flags |= SA_RESTART;
75 if (sigaction(signal, &sigact, nullptr)) {
76 qWarning() << "Could not register handler for POSIX signal:" << ::strerror(errno);
80 void PosixSignalWatcher::signalHandler(int signal)
82 auto bytes = ::write(_sockpair[0], &signal, sizeof(signal));
86 void PosixSignalWatcher::onNotify(int sockfd)
89 auto bytes = ::read(sockfd, &signal, sizeof(signal));
91 quInfo() << "Caught signal" << signal;
95 emit handleSignal(Action::Reload);
99 emit handleSignal(Action::Terminate);
104 emit handleSignal(Action::HandleCrash);