summaryrefslogtreecommitdiffstats
path: root/src/platformsupport
diff options
context:
space:
mode:
Diffstat (limited to 'src/platformsupport')
-rw-r--r--src/platformsupport/eglconvenience/qeglplatformintegration_p.h2
-rw-r--r--src/platformsupport/fbconvenience/qfbvthandler.cpp138
-rw-r--r--src/platformsupport/fbconvenience/qfbvthandler_p.h19
3 files changed, 125 insertions, 34 deletions
diff --git a/src/platformsupport/eglconvenience/qeglplatformintegration_p.h b/src/platformsupport/eglconvenience/qeglplatformintegration_p.h
index 3b6c862333..42fbf8c8a1 100644
--- a/src/platformsupport/eglconvenience/qeglplatformintegration_p.h
+++ b/src/platformsupport/eglconvenience/qeglplatformintegration_p.h
@@ -90,6 +90,8 @@ public:
QFunctionPointer platformFunction(const QByteArray &function) const Q_DECL_OVERRIDE;
+ QFbVtHandler *vtHandler() { return m_vtHandler.data(); }
+
protected:
virtual QEGLPlatformWindow *createWindow(QWindow *window) const = 0;
virtual QEGLPlatformContext *createContext(const QSurfaceFormat &format,
diff --git a/src/platformsupport/fbconvenience/qfbvthandler.cpp b/src/platformsupport/fbconvenience/qfbvthandler.cpp
index d534985129..84844d8eda 100644
--- a/src/platformsupport/fbconvenience/qfbvthandler.cpp
+++ b/src/platformsupport/fbconvenience/qfbvthandler.cpp
@@ -32,72 +32,148 @@
****************************************************************************/
#include "qfbvthandler_p.h"
-#include <QtCore/private/qcrashhandler_p.h>
-#include <QtGui/private/qguiapplication_p.h>
+#include <QtCore/QSocketNotifier>
-#if defined(Q_OS_LINUX) && !defined(QT_NO_EVDEV)
-#define HAS_VT
-#endif
+#if defined(Q_OS_LINUX) && !defined(Q_OS_ANDROID) && (!defined(QT_NO_EVDEV) || !defined(QT_NO_LIBINPUT))
-#ifdef HAS_VT
+#define VTH_ENABLED
+#include <unistd.h>
+#include <signal.h>
+#include <errno.h>
+#include <sys/signalfd.h>
#include <sys/ioctl.h>
#include <linux/kd.h>
+#ifndef KDSKBMUTE
+#define KDSKBMUTE 0x4B51
+#endif
+
#ifdef K_OFF
#define KBD_OFF_MODE K_OFF
#else
#define KBD_OFF_MODE K_RAW
#endif
-#endif // HAS_VT
+#endif
QT_BEGIN_NAMESPACE
-QFbVtHandler *QFbVtHandler::self = 0;
-
QFbVtHandler::QFbVtHandler(QObject *parent)
- : QObject(parent), m_tty(-1)
+ : QObject(parent),
+ m_tty(-1),
+ m_signalFd(-1),
+ m_signalNotifier(0)
{
- Q_ASSERT(!self);
- self = this;
+#ifdef VTH_ENABLED
+ if (isatty(0)) {
+ m_tty = 0;
+ ioctl(m_tty, KDGKBMODE, &m_oldKbdMode);
+
+ if (!qEnvironmentVariableIntValue("QT_QPA_ENABLE_TERMINAL_KEYBOARD")) {
+ // Disable the tty keyboard.
+ ioctl(m_tty, KDSKBMUTE, 1);
+ ioctl(m_tty, KDSKBMODE, KBD_OFF_MODE);
+ }
+ }
-#ifdef HAS_VT
- if (!isatty(0))
- return;
+ // SIGSEGV and such cannot safely be blocked. We cannot handle them in an
+ // async-safe manner either. Restoring the keyboard, video mode, etc. may
+ // all contain calls that cannot safely be made from a signal handler.
- m_tty = 0;
- ::ioctl(m_tty, KDGKBMODE, &m_oldKbdMode);
- if (!qEnvironmentVariableIntValue("QT_QPA_ENABLE_TERMINAL_KEYBOARD")) {
- ::ioctl(m_tty, KDSKBMODE, KBD_OFF_MODE);
- QGuiApplicationPrivate *appd = QGuiApplicationPrivate::instance();
- Q_ASSERT(appd);
- QSegfaultHandler::initialize(appd->argv, appd->argc);
- QSegfaultHandler::installCrashHandler(crashHandler);
+ // Other signals: block them and use signalfd.
+ sigset_t mask;
+ sigemptyset(&mask);
+
+ // Catch Ctrl+C.
+ sigaddset(&mask, SIGINT);
+
+ // Ctrl+Z. Up to the platform plugins to handle it in a meaningful way.
+ sigaddset(&mask, SIGTSTP);
+ sigaddset(&mask, SIGCONT);
+
+ // Default signal used by kill. To overcome the common issue of no cleaning
+ // up when killing a locally started app via a remote session.
+ sigaddset(&mask, SIGTERM);
+
+ m_signalFd = signalfd(-1, &mask, SFD_CLOEXEC);
+ if (m_signalFd < 0) {
+ qErrnoWarning(errno, "signalfd() failed");
+ } else {
+ m_signalNotifier = new QSocketNotifier(m_signalFd, QSocketNotifier::Read, this);
+ connect(m_signalNotifier, &QSocketNotifier::activated, this, &QFbVtHandler::handleSignal);
+
+ // Block the signals that are handled via signalfd. Applies only to the current
+ // thread, but new threads will inherit the creator's signal mask.
+ pthread_sigmask(SIG_BLOCK, &mask, 0);
}
#endif
}
QFbVtHandler::~QFbVtHandler()
{
- self->cleanup();
- self = 0;
+#ifdef VTH_ENABLED
+ restoreKeyboard();
+
+ if (m_signalFd != -1)
+ close(m_signalFd);
+#endif
}
-void QFbVtHandler::cleanup()
+void QFbVtHandler::restoreKeyboard()
{
+#ifdef VTH_ENABLED
if (m_tty == -1)
return;
-#ifdef HAS_VT
- ::ioctl(m_tty, KDSKBMODE, m_oldKbdMode);
+ ioctl(m_tty, KDSKBMUTE, 0);
+ ioctl(m_tty, KDSKBMODE, m_oldKbdMode);
+#endif
+}
+
+// To be called from the slot connected to suspendRequested() in case the
+// platform plugin does in fact allow suspending on Ctrl+Z.
+void QFbVtHandler::suspend()
+{
+#ifdef VTH_ENABLED
+ kill(getpid(), SIGSTOP);
+#endif
+}
+
+void QFbVtHandler::handleSignal()
+{
+#ifdef VTH_ENABLED
+ m_signalNotifier->setEnabled(false);
+
+ signalfd_siginfo sig;
+ if (read(m_signalFd, &sig, sizeof(sig)) == sizeof(sig)) {
+ switch (sig.ssi_signo) {
+ case SIGINT: // fallthrough
+ case SIGTERM:
+ handleInt();
+ break;
+ case SIGTSTP:
+ emit suspendRequested();
+ break;
+ case SIGCONT:
+ emit resumed();
+ break;
+ default:
+ break;
+ }
+ }
+
+ m_signalNotifier->setEnabled(true);
#endif
}
-void QFbVtHandler::crashHandler()
+void QFbVtHandler::handleInt()
{
- Q_ASSERT(self);
- self->cleanup();
+#ifdef VTH_ENABLED
+ emit interrupted();
+ restoreKeyboard();
+ _exit(1);
+#endif
}
QT_END_NAMESPACE
diff --git a/src/platformsupport/fbconvenience/qfbvthandler_p.h b/src/platformsupport/fbconvenience/qfbvthandler_p.h
index 53a39fd58b..3681def9f0 100644
--- a/src/platformsupport/fbconvenience/qfbvthandler_p.h
+++ b/src/platformsupport/fbconvenience/qfbvthandler_p.h
@@ -49,6 +49,8 @@
QT_BEGIN_NAMESPACE
+class QSocketNotifier;
+
class QFbVtHandler : public QObject
{
Q_OBJECT
@@ -57,13 +59,24 @@ public:
QFbVtHandler(QObject *parent = 0);
~QFbVtHandler();
+ void suspend();
+
+signals:
+ void interrupted();
+ void suspendRequested();
+ void resumed();
+
+private slots:
+ void handleSignal();
+
private:
- void cleanup();
- static void crashHandler();
+ void restoreKeyboard();
+ void handleInt();
- static QFbVtHandler *self;
int m_tty;
int m_oldKbdMode;
+ int m_signalFd;
+ QSocketNotifier *m_signalNotifier;
};
QT_END_NAMESPACE