diff --git a/tools/main.cpp b/tools/main.cpp --- a/tools/main.cpp +++ b/tools/main.cpp @@ -1,6 +1,7 @@ /* * Copyright (C) 2010-2018 Daniel Nicoletti * (C) 2011 Modestas Vainius + * (C) 2018 Harald Sitter * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -18,23 +19,62 @@ * Boston, MA 02110-1301, USA. */ -#include -#include -#include -#include +#include +#include +#include +#include +#include #include #include #include +#include +#include +#include +#include + #include using namespace DebconfKde; +// Handle SIGQUIT. Clients (e.g. packagekit) may use QUIT which would otherwise +// result in a core dump. +// Qt methods aren't signal-safe, so we'll defer the handling via a socket +// notification. +static void setupQuitHandler() { + static int quitFD[2]; + if (socketpair(AF_UNIX, SOCK_STREAM, 0, quitFD)) { + qErrnoWarning("Failed to create socket"); + } + auto notifier = new QSocketNotifier(quitFD[1], QSocketNotifier::Read, qApp); + QObject::connect(notifier, &QSocketNotifier::activated, [notifier]() { + notifier->setEnabled(false); + char c; + read(quitFD[1], &c, sizeof(c)); + qApp->quit(); + }); + + struct sigaction sa; + sa.sa_handler = [](int) -> void { + char c = 1; + write(quitFD[0], &c, sizeof(c)); + }; + sigemptyset(&sa.sa_mask); + sigaddset(&sa.sa_mask, SIGQUIT); + sa.sa_flags = 0; + sa.sa_flags |= SA_RESTART; + + if (sigaction(SIGQUIT, &sa, 0) != 0) { + qErrnoWarning("Failed to set quit handler"); + } +} + int main(int argc, char **argv) { QApplication app(argc, argv); + setupQuitHandler(); KLocalizedString::setApplicationDomain("libdebconf-kde");