diff options
author | Robert Griebl <robert.griebl@pelagicore.com> | 2017-03-09 21:42:20 +0100 |
---|---|---|
committer | Dominik Holland <dominik.holland@pelagicore.com> | 2017-03-13 15:44:36 +0000 |
commit | 3df2058ef31adcd10fdd43c71fcbedf1b10e7a19 (patch) | |
tree | 937962a337852bcbf9b8a90e57b08cf494ea1a4c | |
parent | 5e7e7da949977357f4621f6712529231a4c71809 (diff) | |
download | qtapplicationmanager-3df2058ef31adcd10fdd43c71fcbedf1b10e7a19.tar.gz |
common-lib cleanup
global.{h,cpp} and utilities.{h,cpp} have become the kitchensink of the AM.
This commit splits out the logging functionality from global.{h,cpp} into the
new files logging.{h,cpp} and also the crash handling functionality from
utilities.{h,cpp} into the new crashhandler.{h,cpp}
Change-Id: Idffdb424b1cbd8d92eb60b0ac7f08e17a46c749b
Reviewed-by: Dominik Holland <dominik.holland@pelagicore.com>
49 files changed, 910 insertions, 685 deletions
diff --git a/src/common-lib/common-lib.pro b/src/common-lib/common-lib.pro index 2ee61ff9..13481fa7 100644 --- a/src/common-lib/common-lib.pro +++ b/src/common-lib/common-lib.pro @@ -26,7 +26,9 @@ SOURCES += \ startuptimer.cpp \ dbus-policy.cpp \ unixsignalhandler.cpp \ - processtitle.cpp + processtitle.cpp \ + crashhandler.cpp \ + logging.cpp qtHaveModule(qml):SOURCES += \ qml-utilities.cpp \ @@ -43,7 +45,9 @@ HEADERS += \ startuptimer.h \ dbus-policy.h \ unixsignalhandler.h \ - processtitle.h + processtitle.h \ + crashhandler.h \ + logging.h qtHaveModule(qml):HEADERS += \ qml-utilities.h \ diff --git a/src/common-lib/crashhandler.cpp b/src/common-lib/crashhandler.cpp new file mode 100644 index 00000000..637ebcc8 --- /dev/null +++ b/src/common-lib/crashhandler.cpp @@ -0,0 +1,327 @@ +/**************************************************************************** +** +** Copyright (C) 2017 Pelagicore AG +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Pelagicore Application Manager. +** +** $QT_BEGIN_LICENSE:LGPL-QTAS$ +** Commercial License Usage +** Licensees holding valid commercial Qt Automotive Suite licenses may use +** this file in accordance with the commercial license agreement provided +** with the Software or, alternatively, in accordance with the terms +** contained in a written agreement between you and The Qt Company. For +** licensing terms and conditions see https://www.qt.io/terms-conditions. +** For further information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +** SPDX-License-Identifier: LGPL-3.0 +** +****************************************************************************/ + +#include "crashhandler.h" +#include "global.h" + +#if !defined(Q_OS_LINUX) + +QT_BEGIN_NAMESPACE_AM + +void CrashHandler::setCrashActionConfiguration(const QVariantMap &config) +{ + Q_UNUSED(config) +} + +QT_END_NAMESPACE_AM + +#else + +#include <cxxabi.h> +#include <execinfo.h> +#include <setjmp.h> +#include <signal.h> +#include <inttypes.h> + +#if defined(AM_USE_LIBBACKTRACE) +# include <libbacktrace/backtrace.h> +# include <libbacktrace/backtrace-supported.h> +#endif + +#include "unixsignalhandler.h" +#include "utilities.h" +#include "processtitle.h" + +QT_BEGIN_NAMESPACE_AM + +static bool printBacktrace; +static bool useAnsiColor; +static bool dumpCore; +static int waitForGdbAttach; + +static char *demangleBuffer; +static size_t demangleBufferSize; + +// this will make it run before all other static constructor functions +static void initBacktrace() __attribute__((constructor(101))); + +static void crashHandler(const char *why, int stackFramesToIgnore) __attribute__((noreturn)); + +void CrashHandler::setCrashActionConfiguration(const QVariantMap &config) +{ + printBacktrace = config.value(qSL("printBacktrace"), printBacktrace).toBool(); + waitForGdbAttach = config.value(qSL("waitForGdbAttach"), waitForGdbAttach).toInt(); + dumpCore = config.value(qSL("dumpCore"), dumpCore).toBool(); +} + + +static void initBacktrace() +{ + // This can catch and pretty-print all of the following: + + // SIGFPE + // volatile int i = 2; + // int zero = 0; + // i /= zero; + + // SIGSEGV + // *((int *)1) = 1; + + // uncaught arbitrary exception + // throw 42; + + // uncaught std::exception derived exception (prints what()) + // throw std::logic_error("test output"); + + printBacktrace = true; + dumpCore = true; + waitForGdbAttach = false; + + getOutputInformation(&useAnsiColor, nullptr, nullptr); + + demangleBufferSize = 512; + demangleBuffer = (char *) malloc(demangleBufferSize); + + UnixSignalHandler::instance()->install(UnixSignalHandler::RawSignalHandler, + { SIGFPE, SIGSEGV, SIGILL, SIGBUS, SIGPIPE, SIGABRT }, + [](int sig) { + UnixSignalHandler::instance()->resetToDefault(sig); + static char buffer[256]; + snprintf(buffer, sizeof(buffer), "uncaught signal %d (%s)", sig, UnixSignalHandler::signalName(sig)); + // 6 means to remove 6 stack frames: this way the backtrace starts at the point where + // the signal reception interrupted the normal program flow + crashHandler(buffer, 6); + }); + + std::set_terminate([]() { + static char buffer [1024]; + + auto type = abi::__cxa_current_exception_type(); + if (!type) { + // 3 means to remove 3 stack frames: this way the backtrace starts at std::terminate + crashHandler("terminate was called although no exception was thrown", 3); + } + + const char *typeName = type->name(); + if (typeName) { + int status; + abi::__cxa_demangle(typeName, demangleBuffer, &demangleBufferSize, &status); + if (status == 0 && *demangleBuffer) { + typeName = demangleBuffer; + } + } + try { + throw; + } catch (const std::exception &exc) { + snprintf(buffer, sizeof(buffer), "uncaught exception of type %s (%s)", typeName, exc.what()); + } catch (...) { + snprintf(buffer, sizeof(buffer), "uncaught exception of type %s", typeName); + } + + // 4 means to remove 4 stack frames: this way the backtrace starts at std::terminate + crashHandler(buffer, 4); + }); +} + +static void crashHandler(const char *why, int stackFramesToIgnore) +{ + pid_t pid = getpid(); + char who[256]; + int whoLen = readlink("/proc/self/exe", who, sizeof(who) -1); + who[qMax(0, whoLen)] = '\0'; + const char *title = ProcessTitle::title(); + + fprintf(stderr, "\n*** process %s (%d) crashed ***\n\n > why: %s\n", title ? title : who, pid, why); + + if (printBacktrace) { +#if defined(AM_USE_LIBBACKTRACE) && defined(BACKTRACE_SUPPORTED) + struct btData + { + backtrace_state *state; + int level; + }; + + static auto printBacktraceLine = [](int level, const char *symbol, uintptr_t offset, const char *file = nullptr, int line = -1) { + const char *fmt1 = " %3d: %s [%" PRIxPTR "]"; + const char *fmt2 = " in %s:%d"; + if (useAnsiColor) { + fmt1 = " %3d: \x1b[1m%s\x1b[0m [\x1b[36m%" PRIxPTR "\x1b[0m]"; + fmt2 = " in \x1b[35m%s\x1b[0m:\x1b[35;1m%d\x1b[0m"; + } + + fprintf(stderr, fmt1, level, symbol, offset); + if (file) + fprintf(stderr, fmt2, file, line); + fputs("\n", stderr); + }; + + static auto errorCallback = [](void *data, const char *msg, int errnum) { + const char *fmt = " %3d: ERROR: %s (%d)\n"; + if (useAnsiColor) + fmt = " %3d: \x1b[31;1mERROR: \x1b[0;1m%s (%d)\x1b[0m\n"; + + fprintf(stderr, fmt, static_cast<btData *>(data)->level, msg, errnum); + }; + + static auto syminfoCallback = [](void *data, uintptr_t pc, const char *symname, uintptr_t symval, uintptr_t symsize) { + Q_UNUSED(symval) + Q_UNUSED(symsize) + + int level = static_cast<btData *>(data)->level; + if (symname) { + int status; + abi::__cxa_demangle(symname, demangleBuffer, &demangleBufferSize, &status); + + if (status == 0 && *demangleBuffer) + printBacktraceLine(level, demangleBuffer, pc); + else + printBacktraceLine(level, symname, pc); + } else { + printBacktraceLine(level, nullptr, pc); + } + }; + + static auto fullCallback = [](void *data, uintptr_t pc, const char *filename, int lineno, const char *function) -> int { + if (function) { + int status; + abi::__cxa_demangle(function, demangleBuffer, &demangleBufferSize, &status); + + printBacktraceLine(static_cast<btData *>(data)->level, + (status == 0 && *demangleBuffer) ? demangleBuffer : function, + pc, filename ? filename : "<unknown>", lineno); + } else { + backtrace_syminfo (static_cast<btData *>(data)->state, pc, syminfoCallback, errorCallback, data); + } + return 0; + }; + + static auto simpleCallback = [](void *data, uintptr_t pc) -> int { + backtrace_pcinfo(static_cast<btData *>(data)->state, pc, fullCallback, errorCallback, data); + static_cast<btData *>(data)->level++; + return 0; + }; + + struct backtrace_state *state = backtrace_create_state(nullptr, BACKTRACE_SUPPORTS_THREADS, + errorCallback, nullptr); + + fprintf(stderr, "\n > backtrace:\n"); + btData data = { state, 0 }; + //backtrace_print(state, stackFramesToIgnore, stderr); + backtrace_simple(state, stackFramesToIgnore, simpleCallback, errorCallback, &data); +#else // !defined(AM_USE_LIBBACKTRACE) && defined(BACKTRACE_SUPPORTED) + Q_UNUSED(stackFramesToIgnore); + void *addrArray[1024]; + int addrCount = backtrace(addrArray, sizeof(addrArray) / sizeof(*addrArray)); + + if (!addrCount) { + fprintf(stderr, " > no backtrace available\n"); + } else { + char **symbols = backtrace_symbols(addrArray, addrCount); + //backtrace_symbols_fd(addrArray, addrCount, 2); + + if (!symbols) { + fprintf(stderr, " > no symbol names available\n"); + } else { + fprintf(stderr, " > backtrace:\n"); + for (int i = 1; i < addrCount; ++i) { + char *function = nullptr; + char *offset = nullptr; + char *end = nullptr; + + for (char *ptr = symbols[i]; ptr && *ptr; ++ptr) { + if (!function && *ptr == '(') + function = ptr + 1; + else if (function && !offset && *ptr == '+') + offset = ptr; + else if (function && !end && *ptr == ')') + end = ptr; + } + + if (function && offset && end && (function != offset)) { + *offset = 0; + *end = 0; + + int status; + abi::__cxa_demangle(function, demangleBuffer, &demangleBufferSize, &status); + + if (status == 0 && *demangleBuffer) { + fprintf(stderr, " %3d: %s [+%s]\n", i, demangleBuffer, offset + 1); + } else { + fprintf(stderr, " %3d: %s [+%s]\n", i, function, offset + 1); + } + } else { + fprintf(stderr, " %3d: %s\n", i, symbols[i]); + } + } + fprintf(stderr, "\n"); + } + } +#endif // defined(AM_USE_LIBBACKTRACE) && defined(BACKTRACE_SUPPORTED) + } + if (waitForGdbAttach > 0) { + fprintf(stderr, "\n > the process will be suspended for %d seconds and you can attach a debugger to it via\n\n gdb -p %d\n", + waitForGdbAttach, pid); + static jmp_buf jmpenv; + signal(SIGALRM, [](int) { + longjmp(jmpenv, 1); + }); + if (!setjmp(jmpenv)) { + alarm(waitForGdbAttach); + + sigset_t mask; + sigemptyset(&mask); + sigaddset(&mask, SIGALRM); + sigsuspend(&mask); + } else { + fprintf(stderr, "\n > no gdb attached\n"); + } + } + if (dumpCore) { + fprintf(stderr, "\n > the process will be aborted (core dump)\n\n"); + UnixSignalHandler::instance()->resetToDefault({ SIGFPE, SIGSEGV, SIGILL, SIGBUS, SIGPIPE, SIGABRT }); + abort(); + } + _Exit(-1); +} + +QT_END_NAMESPACE_AM + +#endif // !Q_OS_LINUX diff --git a/src/common-lib/crashhandler.h b/src/common-lib/crashhandler.h new file mode 100644 index 00000000..9c6f32d3 --- /dev/null +++ b/src/common-lib/crashhandler.h @@ -0,0 +1,55 @@ +/**************************************************************************** +** +** Copyright (C) 2017 Pelagicore AG +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Pelagicore Application Manager. +** +** $QT_BEGIN_LICENSE:LGPL-QTAS$ +** Commercial License Usage +** Licensees holding valid commercial Qt Automotive Suite licenses may use +** this file in accordance with the commercial license agreement provided +** with the Software or, alternatively, in accordance with the terms +** contained in a written agreement between you and The Qt Company. For +** licensing terms and conditions see https://www.qt.io/terms-conditions. +** For further information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +** SPDX-License-Identifier: LGPL-3.0 +** +****************************************************************************/ + +#pragma once + +#include <QtAppManCommon/global.h> +#include <QVariantMap> + +QT_BEGIN_NAMESPACE_AM + +namespace CrashHandler { + +void setCrashActionConfiguration(const QVariantMap &config); + +} + +QT_END_NAMESPACE_AM diff --git a/src/common-lib/global.cpp b/src/common-lib/global.cpp index 4b0cb491..e69de29b 100644 --- a/src/common-lib/global.cpp +++ b/src/common-lib/global.cpp @@ -1,353 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2017 Pelagicore AG -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the Pelagicore Application Manager. -** -** $QT_BEGIN_LICENSE:LGPL-QTAS$ -** Commercial License Usage -** Licensees holding valid commercial Qt Automotive Suite licenses may use -** this file in accordance with the commercial license agreement provided -** with the Software or, alternatively, in accordance with the terms -** contained in a written agreement between you and The Qt Company. For -** licensing terms and conditions see https://www.qt.io/terms-conditions. -** For further information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -** SPDX-License-Identifier: LGPL-3.0 -** -****************************************************************************/ - -#include <QFile> -#include <QNetworkInterface> -#include <QThreadStorage> -#include <QAtomicInteger> - -#include "global.h" -#include "utilities.h" - -#include <stdio.h> -#if defined(Q_OS_WIN) -Q_CORE_EXPORT void qWinMsgHandler(QtMsgType t, const char* str); -# include <windows.h> -#endif -#if defined(Q_OS_ANDROID) -# include <QCoreApplication> -# include <android/log.h> -#endif - -#if defined(QT_GENIVIEXTRAS_LIB) -# include <QtGeniviExtras/QtDlt> -# include <QtGeniviExtras/QDltRegistration> -#else -# define QDLT_LOGGING_CATEGORY(a,b,c,d) Q_LOGGING_CATEGORY(a,b) -# define QDLT_FALLBACK_CATEGORY(a) -# define QDLT_REGISTER_APPLICATION(a,b) -#endif - -#ifndef QDLT_REGISTER_CONTEXT_ON_FIRST_USE -# define QDLT_REGISTER_CONTEXT_ON_FIRST_USE(a) -#endif - -QT_BEGIN_NAMESPACE_AM - -/* -//! [am-logging-categories] -\list -\li \c am.installer - Installer sub-system -\li \c am.notify - Notification sub-system -\li \c am.qml - QML messages -\li \c am.qml.ipc - QML IPC -\li \c am.runtime.qml - QML runtime -\li \c am.system - General system messages -\li \c am.wayland - Wayland sub-system -\li \c general - General messages not part of any ApplicationManager sub-system -\endlist -//! [am-logging-categories] -*/ -QDLT_REGISTER_CONTEXT_ON_FIRST_USE(true) -QDLT_REGISTER_APPLICATION("PCAM", "Pelagicore Application-Manager") -QDLT_LOGGING_CATEGORY(LogSystem, "am.system", "SYS", "General system messages") -QDLT_LOGGING_CATEGORY(LogInstaller, "am.installer", "INST", "Installer sub-system") -QDLT_LOGGING_CATEGORY(LogWayland, "am.wayland", "WAYL", "Wayland sub-system") -QDLT_LOGGING_CATEGORY(LogQml, "am.qml", "QML", "QML messages") -QDLT_LOGGING_CATEGORY(LogNotifications, "am.notify", "NTFY", "Notification sub-system") -QDLT_LOGGING_CATEGORY(LogQmlRuntime, "am.runtime.qml", "QMRT", "QML runtime") -QDLT_LOGGING_CATEGORY(LogQmlIpc, "am.qml.ipc", "QMIP", "QML IPC") -QDLT_LOGGING_CATEGORY(LogGeneral, "general", "GEN", "General messages not part of any ApplicationManager sub-system") -QDLT_FALLBACK_CATEGORY(LogGeneral) - - -QByteArray colorLogApplicationId = QByteArray(); -bool dltLoggingEnabled = true; - -static void colorLogToStderr(QtMsgType msgType, const QMessageLogContext &context, const QString &message) -{ -#if defined(QT_GENIVIEXTRAS_LIB) - if (dltLoggingEnabled) - QDltRegistration::messageHandler(msgType, context, message); -#endif - - if (msgType < QtDebugMsg || msgType > QtInfoMsg) - msgType = QtCriticalMsg; - - // Try to re-use a 512 byte buffer per thread as much as possible to avoid allocations. - static QThreadStorage<QByteArray> outBuffers; - QByteArray &out = outBuffers.localData(); - if (out.capacity() > 512) - out.clear(); - if (!out.capacity()) - out.reserve(512); - out.resize(0); - - int consoleWidth = -1; - bool ansiColorSupport = false; - bool runningInCreator = false; - getOutputInformation(&ansiColorSupport, &runningInCreator, &consoleWidth); - - // Find out, if we have a valid code location and prepare the output strings - const char *filename = nullptr; - int filenameLength = 0; - char linenumber[8]; - int linenumberLength = 0; - - if (context.line > 0 && context.file && context.file[0]) { - QByteArray ba = QByteArray::fromRawData(context.file, strlen(context.file)); - int pos = -1; -#if defined(Q_OS_WIN) - pos = ba.lastIndexOf('\\'); -#endif - if (pos < 0) - pos = ba.lastIndexOf('/'); - if (pos >= 0) { - filename = context.file + pos + 1; - filenameLength = ba.size() - pos - 1; - - linenumberLength = qsnprintf(linenumber, 8, "%d", qMin(context.line, 9999999)); - if (linenumberLength < 0 || linenumberLength >= int(sizeof(linenumber))) - linenumberLength = 0; - linenumber[linenumberLength] = 0; - } - } - - enum ConsoleColor { Off = 0, Black, Red, Green, Yellow, Blue, Magenta, Cyan, Gray, BrightFlag = 0x80 }; - - // helper function to append ANSI color codes to a string - static auto color = [ansiColorSupport](QByteArray &out, int consoleColor) -> void { - static const char *ansiColors[] = { - "\x1b[1m", // bright - "\x1b[0m", // off - "\x1b[30m", // black - "\x1b[31m", // red - "\x1b[32m", // green - "\x1b[33m", // yellow - "\x1b[34m", // blue - "\x1b[35m", // magenta - "\x1b[36m", // cyan - "\x1b[37m" // gray - }; - - if (!ansiColorSupport) - return; - if (consoleColor & BrightFlag) - out.append(ansiColors[0]); - out.append(ansiColors[1 + (consoleColor & ~BrightFlag)]); - }; - - static const char *msgTypeStr[] = { "DBG ", "WARN", "CRIT", "FATL", "INFO" }; - static const ConsoleColor msgTypeColor[] = { Green, Yellow, Red, Magenta, Blue }; - int categoryLength = strlen(context.category); - QByteArray msg = message.toLocal8Bit(); // sadly this allocates, but there's no other way in Qt - - // the visible character length - int outLength = 10 + strlen(context.category) + msg.length(); // 10 = strlen("[XXXX | ] ") - out.append('['); - - color(out, BrightFlag | msgTypeColor[msgType]); - out.append(msgTypeStr[msgType], 4); // all msgTypeStrs are 4 characters - color(out, Off); - - out.append(" | "); - - color(out, Red + qHash(QByteArray::fromRawData(context.category, categoryLength)) % 7); - out.append(context.category, categoryLength); - color(out, Off); - - if (!colorLogApplicationId.isEmpty()) { - out.append(" | "); - - color(out, Red + qHash(colorLogApplicationId) % 7); - out.append(colorLogApplicationId); - color(out, Off); - - outLength += (3 + colorLogApplicationId.length()); // 3 == strlen(" | ") - } - - out.append("] "); - out.append(msg); - - if (filenameLength && linenumberLength) { - int spacing = 1; - if (consoleWidth > 0) { - // right-align the location mark - spacing = consoleWidth - outLength - linenumberLength - filenameLength - 4; // 4 == strlen(" [:]") - - // keep the location mark right-aligned, even if the message contains newlines - int lastNewline = msg.lastIndexOf('\n'); - if (lastNewline >= 0) - spacing += (outLength - msg.length() + lastNewline + 1); - - // keep the location mark right-aligned, even if the message is longer than the window width - while (spacing < 0) - spacing += consoleWidth; - } -#if QT_VERSION < QT_VERSION_CHECK(5,7,0) - // efficiently appending spaces without allocating is hard in Qt 5.6 - static const char spacingStr[] = " "; - Q_STATIC_ASSERT(sizeof(spacingStr) == 80); - while (spacing > 0) { - int spacingLen = qMin(spacing, int(sizeof(spacingStr)) - 1); - out.append(spacingStr, spacingLen); - spacing -= spacingLen; - } -#else - out.append(spacing, ' '); -#endif - out.append('['); - - color(out, Magenta); - out.append(filename, filenameLength); - color(out, Off); - - out.append(':'); - - color(out, BrightFlag | Magenta); - out.append(linenumber, linenumberLength); - color(out, Off); - - out.append("]\n"); - } else { - out.append('\n'); - } - - if (consoleWidth <= 0) { -#if defined(Q_OS_WIN) - // do not use QMutex to avoid possible recursions - static CRITICAL_SECTION cs; - static bool csInitialized = false; - if (!csInitialized) - InitializeCriticalSection(&cs); - - EnterCriticalSection(&cs); - OutputDebugStringA(out.constData()); - LeaveCriticalSection(&cs); - return; - -#elif defined(Q_OS_ANDROID) - android_LogPriority pri = ANDROID_LOG_DEBUG; - switch (msgType) { - default: - case QtDebugMsg: pri = ANDROID_LOG_DEBUG; break; - case QtWarningMsg: pri = ANDROID_LOG_WARN; break; - case QtCriticalMsg: pri = ANDROID_LOG_ERROR; break; - case QtFatalMsg: pri = ANDROID_LOG_FATAL; break; - }; - - static QByteArray appName = QCoreApplication::applicationName().toLocal8Bit(); - - __android_log_print(pri, appName.constData(), out.constData()); - return; -#endif - } - fputs(out.constData(), stderr); -} - -#if defined(QT_GENIVIEXTRAS_LIB) - -static QtMessageHandler defaultQtMsgHandler; - -static void compositeMsgHandler(QtMsgType msgType, const QMessageLogContext &context, const QString &message) -{ - if (dltLoggingEnabled) - QDltRegistration::messageHandler(msgType, context, message); - defaultQtMsgHandler(msgType, context, message); -} - -#endif - -void installMessageHandlers() -{ - if (Q_LIKELY(!qEnvironmentVariableIsSet("QT_MESSAGE_PATTERN"))) - qInstallMessageHandler(colorLogToStderr); -#if defined(QT_GENIVIEXTRAS_LIB) - else - defaultQtMsgHandler = qInstallMessageHandler(compositeMsgHandler); -#endif -} - -QString hardwareId() -{ -#if defined(AM_HARDWARE_ID) - return QString::fromLocal8Bit(AM_HARDWARE_ID); -#elif defined(AM_HARDWARE_ID_FROM_FILE) - QFile f(QString::fromLocal8Bit(AM_HARDWARE_ID_FROM_FILE)); - if (f.open(QFile::ReadOnly)) - return f.readAll().trimmed(); -#else - foreach (const QNetworkInterface &iface, QNetworkInterface::allInterfaces()) { - if (iface.isValid() && (iface.flags() & QNetworkInterface::IsUp) - && !(iface.flags() & (QNetworkInterface::IsPointToPoint | QNetworkInterface::IsLoopBack)) - && !iface.hardwareAddress().isEmpty()) { - return iface.hardwareAddress().replace(qL1C(':'), qL1S("-")); - } - } -#endif - return QString(); -} - -void am_trace(QDebug) -{ } - -void registerUnregisteredDLTContexts() -{ - if (!dltLoggingEnabled) - return; -#ifdef AM_GENIVIEXTRAS_LAZY_INIT - globalDltRegistration()->registerUnregisteredContexts(); -#endif -} - -void changeDLTApplication(const char *dltAppID, const char *dltAppDescription) -{ - if (!dltLoggingEnabled) - return; -#if defined(QT_GENIVIEXTRAS_LIB) - globalDltRegistration()->registerApplication(dltAppID, dltAppDescription); -#else - Q_UNUSED(dltAppID) - Q_UNUSED(dltAppDescription) -#endif -} - -QT_END_NAMESPACE_AM diff --git a/src/common-lib/global.h b/src/common-lib/global.h index ce8ae9b0..18d35061 100644 --- a/src/common-lib/global.h +++ b/src/common-lib/global.h @@ -41,44 +41,15 @@ #pragma once #include <qglobal.h> -#include <QLoggingCategory> #define QT_BEGIN_NAMESPACE_AM namespace QtAM { #define QT_END_NAMESPACE_AM } #define QT_USE_NAMESPACE_AM using namespace QtAM; #define QT_PREPEND_NAMESPACE_AM(name) QtAM::name -QT_BEGIN_NAMESPACE_AM - -Q_DECLARE_LOGGING_CATEGORY(LogSystem) -Q_DECLARE_LOGGING_CATEGORY(LogInstaller) -Q_DECLARE_LOGGING_CATEGORY(LogWayland) -Q_DECLARE_LOGGING_CATEGORY(LogQml) -Q_DECLARE_LOGGING_CATEGORY(LogNotifications) -Q_DECLARE_LOGGING_CATEGORY(LogQmlRuntime) -Q_DECLARE_LOGGING_CATEGORY(LogQmlIpc) - -void registerUnregisteredDLTContexts(); -void changeDLTApplication(const char *dltAppID, const char *dltAppDescription); - -void installMessageHandlers(); - -extern QByteArray colorLogApplicationId; -extern bool dltLoggingEnabled; - -QString hardwareId(); - -void am_trace(QDebug); -template <typename T, typename... TRest> void am_trace(QDebug dbg, T t, TRest... trest) -{ dbg << t; am_trace(dbg, trest...); } - +QT_BEGIN_NAMESPACE_AM // make sure the namespace exists QT_END_NAMESPACE_AM -#define AM_TRACE(category, ...) \ - for (bool qt_category_enabled = category().isDebugEnabled(); qt_category_enabled; qt_category_enabled = false) { \ - QT_PREPEND_NAMESPACE_AM(am_trace(QMessageLogger(__FILE__, __LINE__, __FUNCTION__, category().categoryName()).debug(), "TRACE", __FUNCTION__, __VA_ARGS__)); \ - } - // make the source a lot less ugly and more readable (until we can finally use user defined literals) #define qL1S(x) QLatin1String(x) #define qL1C(x) QLatin1Char(x) diff --git a/src/common-lib/logging.cpp b/src/common-lib/logging.cpp new file mode 100644 index 00000000..47272549 --- /dev/null +++ b/src/common-lib/logging.cpp @@ -0,0 +1,350 @@ +/**************************************************************************** +** +** Copyright (C) 2017 Pelagicore AG +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Pelagicore Application Manager. +** +** $QT_BEGIN_LICENSE:LGPL-QTAS$ +** Commercial License Usage +** Licensees holding valid commercial Qt Automotive Suite licenses may use +** this file in accordance with the commercial license agreement provided +** with the Software or, alternatively, in accordance with the terms +** contained in a written agreement between you and The Qt Company. For +** licensing terms and conditions see https://www.qt.io/terms-conditions. +** For further information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +** SPDX-License-Identifier: LGPL-3.0 +** +****************************************************************************/ + +#include <QThreadStorage> +#include <QAtomicInteger> + +#include "global.h" +#include "logging.h" +#include "utilities.h" + +#include <stdio.h> +#if defined(Q_OS_WIN) +Q_CORE_EXPORT void qWinMsgHandler(QtMsgType t, const char* str); +# include <windows.h> +#endif +#if defined(Q_OS_ANDROID) +# include <QCoreApplication> +# include <android/log.h> +#endif + +#if defined(QT_GENIVIEXTRAS_LIB) +# include <QtGeniviExtras/QtDlt> +# include <QtGeniviExtras/QDltRegistration> +#else +# define QDLT_LOGGING_CATEGORY(a,b,c,d) Q_LOGGING_CATEGORY(a,b) +# define QDLT_FALLBACK_CATEGORY(a) +# define QDLT_REGISTER_APPLICATION(a,b) +#endif + +#ifndef QDLT_REGISTER_CONTEXT_ON_FIRST_USE +# define QDLT_REGISTER_CONTEXT_ON_FIRST_USE(a) +#endif + +QT_BEGIN_NAMESPACE_AM + +/* +//! [am-logging-categories] +\list +\li \c am.installer - Installer sub-system +\li \c am.notify - Notification sub-system +\li \c am.qml - QML messages +\li \c am.qml.ipc - QML IPC +\li \c am.runtime.qml - QML runtime +\li \c am.system - General system messages +\li \c am.wayland - Wayland sub-system +\li \c general - General messages not part of any ApplicationManager sub-system +\endlist +//! [am-logging-categories] +*/ +QDLT_REGISTER_CONTEXT_ON_FIRST_USE(true) +QDLT_REGISTER_APPLICATION("PCAM", "Pelagicore Application-Manager") +QDLT_LOGGING_CATEGORY(LogSystem, "am.system", "SYS", "General system messages") +QDLT_LOGGING_CATEGORY(LogInstaller, "am.installer", "INST", "Installer sub-system") +QDLT_LOGGING_CATEGORY(LogWayland, "am.wayland", "WAYL", "Wayland sub-system") +QDLT_LOGGING_CATEGORY(LogQml, "am.qml", "QML", "QML messages") +QDLT_LOGGING_CATEGORY(LogNotifications, "am.notify", "NTFY", "Notification sub-system") +QDLT_LOGGING_CATEGORY(LogQmlRuntime, "am.runtime.qml", "QMRT", "QML runtime") +QDLT_LOGGING_CATEGORY(LogQmlIpc, "am.qml.ipc", "QMIP", "QML IPC") +QDLT_LOGGING_CATEGORY(LogGeneral, "general", "GEN", "General messages not part of any ApplicationManager sub-system") +QDLT_FALLBACK_CATEGORY(LogGeneral) + + +bool Logging::s_dltEnabled = +#if defined(QT_GENIVIEXTRAS_LIB) + true; +#else + false; +#endif +bool Logging::s_useDefaultQtHandler = false; +QtMessageHandler Logging::s_defaultQtHandler = nullptr; +QByteArray Logging::s_applicationId = QByteArray(); + + +static void colorLogToStderr(QtMsgType msgType, const QMessageLogContext &context, const QString &message) +{ + if (msgType < QtDebugMsg || msgType > QtInfoMsg) + msgType = QtCriticalMsg; + + // Try to re-use a 512 byte buffer per thread as much as possible to avoid allocations. + static QThreadStorage<QByteArray> outBuffers; + QByteArray &out = outBuffers.localData(); + if (out.capacity() > 512) + out.clear(); + if (!out.capacity()) + out.reserve(512); + out.resize(0); + + int consoleWidth = -1; + bool ansiColorSupport = false; + bool runningInCreator = false; + getOutputInformation(&ansiColorSupport, &runningInCreator, &consoleWidth); + + // Find out, if we have a valid code location and prepare the output strings + const char *filename = nullptr; + int filenameLength = 0; + char linenumber[8]; + int linenumberLength = 0; + + if (context.line > 0 && context.file && context.file[0]) { + QByteArray ba = QByteArray::fromRawData(context.file, strlen(context.file)); + int pos = -1; +#if defined(Q_OS_WIN) + pos = ba.lastIndexOf('\\'); +#endif + if (pos < 0) + pos = ba.lastIndexOf('/'); + if (pos >= 0) { + filename = context.file + pos + 1; + filenameLength = ba.size() - pos - 1; + + linenumberLength = qsnprintf(linenumber, 8, "%d", qMin(context.line, 9999999)); + if (linenumberLength < 0 || linenumberLength >= int(sizeof(linenumber))) + linenumberLength = 0; + linenumber[linenumberLength] = 0; + } + } + + enum ConsoleColor { Off = 0, Black, Red, Green, Yellow, Blue, Magenta, Cyan, Gray, BrightFlag = 0x80 }; + + // helper function to append ANSI color codes to a string + static auto color = [ansiColorSupport](QByteArray &out, int consoleColor) -> void { + static const char *ansiColors[] = { + "\x1b[1m", // bright + "\x1b[0m", // off + "\x1b[30m", // black + "\x1b[31m", // red + "\x1b[32m", // green + "\x1b[33m", // yellow + "\x1b[34m", // blue + "\x1b[35m", // magenta + "\x1b[36m", // cyan + "\x1b[37m" // gray + }; + + if (!ansiColorSupport) + return; + if (consoleColor & BrightFlag) + out.append(ansiColors[0]); + out.append(ansiColors[1 + (consoleColor & ~BrightFlag)]); + }; + + static const char *msgTypeStr[] = { "DBG ", "WARN", "CRIT", "FATL", "INFO" }; + static const ConsoleColor msgTypeColor[] = { Green, Yellow, Red, Magenta, Blue }; + int categoryLength = strlen(context.category); + QByteArray msg = message.toLocal8Bit(); // sadly this allocates, but there's no other way in Qt + + // the visible character length + int outLength = 10 + strlen(context.category) + msg.length(); // 10 = strlen("[XXXX | ] ") + out.append('['); + + color(out, BrightFlag | msgTypeColor[msgType]); + out.append(msgTypeStr[msgType], 4); // all msgTypeStrs are 4 characters + color(out, Off); + + out.append(" | "); + + color(out, Red + qHash(QByteArray::fromRawData(context.category, categoryLength)) % 7); + out.append(context.category, categoryLength); + color(out, Off); + + const QByteArray appId = Logging::applicationId(); + if (!appId.isEmpty()) { + out.append(" | "); + + color(out, Red + qHash(appId) % 7); + out.append(appId); + color(out, Off); + + outLength += (3 + appId.length()); // 3 == strlen(" | ") + } + + out.append("] "); + out.append(msg); + + if (filenameLength && linenumberLength) { + int spacing = 1; + if (consoleWidth > 0) { + // right-align the location mark + spacing = consoleWidth - outLength - linenumberLength - filenameLength - 4; // 4 == strlen(" [:]") + + // keep the location mark right-aligned, even if the message contains newlines + int lastNewline = msg.lastIndexOf('\n'); + if (lastNewline >= 0) + spacing += (outLength - msg.length() + lastNewline + 1); + + // keep the location mark right-aligned, even if the message is longer than the window width + while (spacing < 0) + spacing += consoleWidth; + } +#if QT_VERSION < QT_VERSION_CHECK(5,7,0) + // efficiently appending spaces without allocating is hard in Qt 5.6 + static const char spacingStr[] = " "; + Q_STATIC_ASSERT(sizeof(spacingStr) == 80); + while (spacing > 0) { + int spacingLen = qMin(spacing, int(sizeof(spacingStr)) - 1); + out.append(spacingStr, spacingLen); + spacing -= spacingLen; + } +#else + out.append(spacing, ' '); +#endif + out.append('['); + + color(out, Magenta); + out.append(filename, filenameLength); + color(out, Off); + + out.append(':'); + + color(out, BrightFlag | Magenta); + out.append(linenumber, linenumberLength); + color(out, Off); + + out.append("]\n"); + } else { + out.append('\n'); + } + + if (consoleWidth <= 0) { +#if defined(Q_OS_WIN) + // do not use QMutex to avoid possible recursions + static CRITICAL_SECTION cs; + static bool csInitialized = false; + if (!csInitialized) + InitializeCriticalSection(&cs); + + EnterCriticalSection(&cs); + OutputDebugStringA(out.constData()); + LeaveCriticalSection(&cs); + return; + +#elif defined(Q_OS_ANDROID) + android_LogPriority pri = ANDROID_LOG_DEBUG; + switch (msgType) { + default: + case QtDebugMsg: pri = ANDROID_LOG_DEBUG; break; + case QtWarningMsg: pri = ANDROID_LOG_WARN; break; + case QtCriticalMsg: pri = ANDROID_LOG_ERROR; break; + case QtFatalMsg: pri = ANDROID_LOG_FATAL; break; + }; + + static QByteArray appName = QCoreApplication::applicationName().toLocal8Bit(); + + __android_log_print(pri, appName.constData(), out.constData()); + return; +#endif + } + fputs(out.constData(), stderr); +} + +void Logging::initialize() +{ + auto messageHandler = [](QtMsgType msgType, const QMessageLogContext &context, const QString &message) { +#if defined(QT_GENIVIEXTRAS_LIB) + if (s_dltEnabled) + QDltRegistration::messageHandler(msgType, context, message); +#endif + if (Q_UNLIKELY(s_useDefaultQtHandler)) + s_defaultQtHandler(msgType, context, message); + else + colorLogToStderr(msgType, context, message); + }; + + s_useDefaultQtHandler = qEnvironmentVariableIsSet("QT_MESSAGE_PATTERN"); + s_defaultQtHandler = qInstallMessageHandler(messageHandler); +} + +QByteArray Logging::applicationId() +{ + return s_applicationId; +} + +void Logging::setApplicationId(const QByteArray &appId) +{ + s_applicationId = appId; +} + +bool Logging::isDltEnabled() +{ + return s_dltEnabled; +} + +void Logging::setDltEnabled(bool enabled) +{ + s_dltEnabled = enabled; +} + +void Logging::registerUnregisteredDltContexts() +{ + if (!s_dltEnabled) + return; +#ifdef AM_GENIVIEXTRAS_LAZY_INIT + globalDltRegistration()->registerUnregisteredContexts(); +#endif +} + +void Logging::setDltApplicationId(const QByteArray &dltAppId, const QByteArray &dltAppDescription) +{ + if (!s_dltEnabled) + return; +#if defined(QT_GENIVIEXTRAS_LIB) + globalDltRegistration()->registerApplication(dltAppId, dltAppDescription); +#else + Q_UNUSED(dltAppId) + Q_UNUSED(dltAppDescription) +#endif +} + +void am_trace(QDebug) +{ } + +QT_END_NAMESPACE_AM diff --git a/src/common-lib/logging.h b/src/common-lib/logging.h new file mode 100644 index 00000000..0b8a61cb --- /dev/null +++ b/src/common-lib/logging.h @@ -0,0 +1,89 @@ +/**************************************************************************** +** +** Copyright (C) 2017 Pelagicore AG +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Pelagicore Application Manager. +** +** $QT_BEGIN_LICENSE:LGPL-QTAS$ +** Commercial License Usage +** Licensees holding valid commercial Qt Automotive Suite licenses may use +** this file in accordance with the commercial license agreement provided +** with the Software or, alternatively, in accordance with the terms +** contained in a written agreement between you and The Qt Company. For +** licensing terms and conditions see https://www.qt.io/terms-conditions. +** For further information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +** SPDX-License-Identifier: LGPL-3.0 +** +****************************************************************************/ + +#pragma once + +#include "global.h" +#include <QLoggingCategory> + +QT_BEGIN_NAMESPACE_AM + +Q_DECLARE_LOGGING_CATEGORY(LogSystem) +Q_DECLARE_LOGGING_CATEGORY(LogInstaller) +Q_DECLARE_LOGGING_CATEGORY(LogWayland) +Q_DECLARE_LOGGING_CATEGORY(LogQml) +Q_DECLARE_LOGGING_CATEGORY(LogNotifications) +Q_DECLARE_LOGGING_CATEGORY(LogQmlRuntime) +Q_DECLARE_LOGGING_CATEGORY(LogQmlIpc) + +class Logging +{ +public: + static void initialize(); + + static QByteArray applicationId(); + static void setApplicationId(const QByteArray &appId); + + // DLT functionality + static bool isDltEnabled(); + static void setDltEnabled(bool enabled); + + static void registerUnregisteredDltContexts(); + static void setDltApplicationId(const QByteArray &dltAppId, const QByteArray &dltAppDescription); + +private: + static bool s_dltEnabled; + static bool s_useDefaultQtHandler; + static QtMessageHandler s_defaultQtHandler; + static QByteArray s_applicationId; +}; + + +void am_trace(QDebug); +template <typename T, typename... TRest> void am_trace(QDebug dbg, T t, TRest... trest) +{ dbg << t; am_trace(dbg, trest...); } + +#define AM_TRACE(category, ...) \ + for (bool qt_category_enabled = category().isDebugEnabled(); qt_category_enabled; qt_category_enabled = false) { \ + QT_PREPEND_NAMESPACE_AM(am_trace(QMessageLogger(__FILE__, __LINE__, __FUNCTION__, category().categoryName()).debug(), "TRACE", __FUNCTION__, __VA_ARGS__)); \ + } + +QT_END_NAMESPACE_AM diff --git a/src/common-lib/processtitle.cpp b/src/common-lib/processtitle.cpp index 0b799037..61a07f2a 100644 --- a/src/common-lib/processtitle.cpp +++ b/src/common-lib/processtitle.cpp @@ -48,6 +48,8 @@ const char *ProcessTitle::title() { return nullptr; } QT_END_NAMESPACE_AM #else +#include "logging.h" + #include <QVarLengthArray> #include <QByteArray> diff --git a/src/common-lib/processtitle.h b/src/common-lib/processtitle.h index 67a687af..e4ad2527 100644 --- a/src/common-lib/processtitle.h +++ b/src/common-lib/processtitle.h @@ -41,7 +41,6 @@ #pragma once -#include <stdlib.h> #include <QtAppManCommon/global.h> QT_BEGIN_NAMESPACE_AM diff --git a/src/common-lib/unixsignalhandler.cpp b/src/common-lib/unixsignalhandler.cpp index ba4b2c8f..997a8df2 100644 --- a/src/common-lib/unixsignalhandler.cpp +++ b/src/common-lib/unixsignalhandler.cpp @@ -40,6 +40,7 @@ ****************************************************************************/ #include "unixsignalhandler.h" +#include "logging.h" #include <QSocketNotifier> #include <QCoreApplication> diff --git a/src/common-lib/unixsignalhandler.h b/src/common-lib/unixsignalhandler.h index fa4d79e0..d126231a 100644 --- a/src/common-lib/unixsignalhandler.h +++ b/src/common-lib/unixsignalhandler.h @@ -41,8 +41,9 @@ #pragma once -#include <QAtomicInteger> #include <QtAppManCommon/global.h> +#include <QObject> +#include <QAtomicInteger> #include <initializer_list> #include <list> #include <vector> diff --git a/src/common-lib/utilities.cpp b/src/common-lib/utilities.cpp index 34e50d18..fe1cf827 100644 --- a/src/common-lib/utilities.cpp +++ b/src/common-lib/utilities.cpp @@ -48,11 +48,11 @@ #include <QFileInfo> #include <QFile> #include <QCoreApplication> +#include <QNetworkInterface> #include "utilities.h" #include "exception.h" #include "unixsignalhandler.h" -#include "processtitle.h" #include <errno.h> @@ -91,6 +91,26 @@ extern char **environ; QT_BEGIN_NAMESPACE_AM +QString hardwareId() +{ +#if defined(AM_HARDWARE_ID) + return QString::fromLocal8Bit(AM_HARDWARE_ID); +#elif defined(AM_HARDWARE_ID_FROM_FILE) + QFile f(QString::fromLocal8Bit(AM_HARDWARE_ID_FROM_FILE)); + if (f.open(QFile::ReadOnly)) + return f.readAll().trimmed(); +#else + foreach (const QNetworkInterface &iface, QNetworkInterface::allInterfaces()) { + if (iface.isValid() && (iface.flags() & QNetworkInterface::IsUp) + && !(iface.flags() & (QNetworkInterface::IsPointToPoint | QNetworkInterface::IsLoopBack)) + && !iface.hardwareAddress().isEmpty()) { + return iface.hardwareAddress().replace(qL1C(':'), qL1S("-")); + } + } +#endif + return QString(); +} + bool ensureCorrectLocale() { // We need to make sure we are running in a Unicode locale, since we are @@ -475,279 +495,6 @@ QString findOnSDCard(const QString &file) #endif -#if defined(Q_OS_LINUX) - -QT_END_NAMESPACE_AM - -#include <cxxabi.h> -#include <execinfo.h> -#include <setjmp.h> -#include <signal.h> -#include <inttypes.h> - -#if defined(AM_USE_LIBBACKTRACE) -# include <libbacktrace/backtrace.h> -# include <libbacktrace/backtrace-supported.h> -#endif -QT_BEGIN_NAMESPACE_AM - -static bool printBacktrace; -static bool useAnsiColor; -static bool dumpCore; -static int waitForGdbAttach; - -static char *demangleBuffer; -static size_t demangleBufferSize; - - -static void crashHandler(const char *why, int stackFramesToIgnore) __attribute__((noreturn)); - -static void crashHandler(const char *why, int stackFramesToIgnore) -{ - pid_t pid = getpid(); - char who[256]; - int whoLen = readlink("/proc/self/exe", who, sizeof(who) -1); - who[qMax(0, whoLen)] = '\0'; - const char *title = ProcessTitle::title(); - - fprintf(stderr, "\n*** process %s (%d) crashed ***\n\n > why: %s\n", title ? title : who, pid, why); - - if (printBacktrace) { -#if defined(AM_USE_LIBBACKTRACE) && defined(BACKTRACE_SUPPORTED) - struct btData { - backtrace_state *state; - int level; - }; - - static auto printBacktraceLine = [](int level, const char *symbol, uintptr_t offset, const char *file = nullptr, int line = -1) - { - if (useAnsiColor) { - fprintf(stderr, " %3d: \x1b[1m%s\x1b[0m [\x1b[36m%" PRIxPTR "\x1b[0m]", level, symbol, offset); - if (file) - fprintf(stderr, " in \x1b[35m%s\x1b[0m:\x1b[35;1m%d\x1b[0m", file, line); - } else { - fprintf(stderr, " %3d: %s [%" PRIxPTR "]", level, symbol, offset); - if (file) - fprintf(stderr, " in %s:%d", file, line); - } - fputs("\n", stderr); - }; - - static auto errorCallback = [](void *data, const char *msg, int errnum) { - if (useAnsiColor) - fprintf(stderr, " %3d: \x1b[31;1mERROR: \x1b[0;1m%s (%d)\x1b[0m\n", static_cast<btData *>(data)->level, msg, errnum); - else - fprintf(stderr, " %3d: ERROR: %s (%d)\n", static_cast<btData *>(data)->level, msg, errnum); - }; - - static auto syminfoCallback = [](void *data, uintptr_t pc, const char *symname, uintptr_t symval, uintptr_t symsize) { - Q_UNUSED(symval) - Q_UNUSED(symsize) - - int level = static_cast<btData *>(data)->level; - if (symname) { - int status; - abi::__cxa_demangle(symname, demangleBuffer, &demangleBufferSize, &status); - - if (status == 0 && *demangleBuffer) - printBacktraceLine(level, demangleBuffer, pc); - else - printBacktraceLine(level, symname, pc); - } else { - printBacktraceLine(level, nullptr, pc); - } - }; - - static auto fullCallback = [](void *data, uintptr_t pc, const char *filename, int lineno, const char *function) -> int { - if (function) { - int status; - abi::__cxa_demangle(function, demangleBuffer, &demangleBufferSize, &status); - - printBacktraceLine(static_cast<btData *>(data)->level, - (status == 0 && *demangleBuffer) ? demangleBuffer : function, - pc, filename ? filename : "<unknown>", lineno); - } else { - backtrace_syminfo (static_cast<btData *>(data)->state, pc, syminfoCallback, errorCallback, data); - } - return 0; - }; - - static auto simpleCallback = [](void *data, uintptr_t pc) -> int { - backtrace_pcinfo(static_cast<btData *>(data)->state, pc, fullCallback, errorCallback, data); - static_cast<btData *>(data)->level++; - return 0; - }; - - struct backtrace_state *state = backtrace_create_state(nullptr, BACKTRACE_SUPPORTS_THREADS, - errorCallback, nullptr); - - fprintf(stderr, "\n > backtrace:\n"); - btData data = { state, 0 }; - //backtrace_print(state, stackFramesToIgnore, stderr); - backtrace_simple(state, stackFramesToIgnore, simpleCallback, errorCallback, &data); -#else - Q_UNUSED(stackFramesToIgnore); - void *addrArray[1024]; - int addrCount = backtrace(addrArray, sizeof(addrArray) / sizeof(*addrArray)); - - if (!addrCount) { - fprintf(stderr, " > no backtrace available\n"); - } else { - char **symbols = backtrace_symbols(addrArray, addrCount); - //backtrace_symbols_fd(addrArray, addrCount, 2); - - if (!symbols) { - fprintf(stderr, " > no symbol names available\n"); - } else { - fprintf(stderr, " > backtrace:\n"); - for (int i = 1; i < addrCount; ++i) { - char *function = nullptr; - char *offset = nullptr; - char *end = nullptr; - - for (char *ptr = symbols[i]; ptr && *ptr; ++ptr) { - if (!function && *ptr == '(') - function = ptr + 1; - else if (function && !offset && *ptr == '+') - offset = ptr; - else if (function && !end && *ptr == ')') - end = ptr; - } - - if (function && offset && end && (function != offset)) { - *offset = 0; - *end = 0; - - int status; - abi::__cxa_demangle(function, demangleBuffer, &demangleBufferSize, &status); - - if (status == 0 && *demangleBuffer) { - fprintf(stderr, " %3d: %s [+%s]\n", i, demangleBuffer, offset + 1); - } else { - fprintf(stderr, " %3d: %s [+%s]\n", i, function, offset + 1); - } - } else { - fprintf(stderr, " %3d: %s\n", i, symbols[i]); - } - } - fprintf(stderr, "\n"); - } - } -#endif - } - if (waitForGdbAttach > 0) { - fprintf(stderr, "\n > the process will be suspended for %d seconds and you can attach a debugger to it via\n\n gdb -p %d\n", - waitForGdbAttach, pid); - static jmp_buf jmpenv; - signal(SIGALRM, [](int) { - longjmp(jmpenv, 1); - }); - if (!setjmp(jmpenv)) { - alarm(waitForGdbAttach); - - sigset_t mask; - sigemptyset(&mask); - sigaddset(&mask, SIGALRM); - sigsuspend(&mask); - } else { - fprintf(stderr, "\n > no gdb attached\n"); - } - } - if (dumpCore) { - fprintf(stderr, "\n > the process will be aborted (core dump)\n\n"); - UnixSignalHandler::instance()->resetToDefault({ SIGFPE, SIGSEGV, SIGILL, SIGBUS, SIGPIPE, SIGABRT }); - abort(); - } - _Exit(-1); -} - -// this will make it run before all other static constructor functions -static void initBacktrace() __attribute__((constructor(1000))); - -static void initBacktrace() -{ - // This can catch and pretty-print all of the following: - - // SIGFPE - // volatile int i = 2; - // int zero = 0; - // i /= zero; - - // SIGSEGV - // *((int *)1) = 1; - - // uncaught arbitrary exception - // throw 42; - - // uncaught std::exception derived exception (prints what()) - // throw std::logic_error("test output"); - - printBacktrace = true; - dumpCore = true; - waitForGdbAttach = false; - - getOutputInformation(&useAnsiColor, nullptr, nullptr); - - demangleBufferSize = 512; - demangleBuffer = (char *) malloc(demangleBufferSize); - - UnixSignalHandler::instance()->install(UnixSignalHandler::RawSignalHandler, - { SIGFPE, SIGSEGV, SIGILL, SIGBUS, SIGPIPE, SIGABRT }, - [](int sig) { - UnixSignalHandler::instance()->resetToDefault(sig); - static char buffer[256]; - snprintf(buffer, sizeof(buffer), "uncaught signal %d (%s)", sig, UnixSignalHandler::signalName(sig)); - // 6 means to remove 6 stack frames: this way the backtrace starts at the point where - // the signal reception interrupted the normal program flow - crashHandler(buffer, 6); - }); - - std::set_terminate([]() { - static char buffer [1024]; - - auto type = abi::__cxa_current_exception_type(); - if (!type) { - // 3 means to remove 3 stack frames: this way the backtrace starts at std::terminate - crashHandler("terminate was called although no exception was thrown", 3); - } - - const char *typeName = type->name(); - if (typeName) { - int status; - abi::__cxa_demangle(typeName, demangleBuffer, &demangleBufferSize, &status); - if (status == 0 && *demangleBuffer) { - typeName = demangleBuffer; - } - } - try { - throw; - } catch (const std::exception &exc) { - snprintf(buffer, sizeof(buffer), "uncaught exception of type %s (%s)", typeName, exc.what()); - } catch (...) { - snprintf(buffer, sizeof(buffer), "uncaught exception of type %s", typeName); - } - - // 4 means to remove 4 stack frames: this way the backtrace starts at std::terminate - crashHandler(buffer, 4); - }); -} - -void setCrashActionConfiguration(const QVariantMap &config) -{ - printBacktrace = config.value(qSL("printBacktrace"), printBacktrace).toBool(); - waitForGdbAttach = config.value(qSL("waitForGdbAttach"), waitForGdbAttach).toInt(); - dumpCore = config.value(qSL("dumpCore"), dumpCore).toBool(); -} - -#else // Q_OS_LINUX - -void setCrashActionConfiguration(const QVariantMap &config) -{ - Q_UNUSED(config) -} - -#endif // !Q_OS_LINUX - void getOutputInformation(bool *ansiColorSupport, bool *runningInCreator, int *consoleWidth) { static bool ansiColorSupportDetected = false; diff --git a/src/common-lib/utilities.h b/src/common-lib/utilities.h index bac006ee..2a280167 100644 --- a/src/common-lib/utilities.h +++ b/src/common-lib/utilities.h @@ -62,6 +62,8 @@ QT_BEGIN_NAMESPACE_AM +QString hardwareId(); + bool ensureCorrectLocale(); bool checkCorrectLocale(); @@ -182,8 +184,6 @@ private: QString findOnSDCard(const QString &file); #endif -void setCrashActionConfiguration(const QVariantMap &config); - void getOutputInformation(bool *ansiColorSupport, bool *runningInCreator, int *consoleWidth); qint64 getParentPid(qint64 pid); diff --git a/src/installer-lib/applicationinstaller.cpp b/src/installer-lib/applicationinstaller.cpp index f6bc9a71..c3ef7416 100644 --- a/src/installer-lib/applicationinstaller.cpp +++ b/src/installer-lib/applicationinstaller.cpp @@ -43,6 +43,7 @@ #include <QDir> #include <QUuid> +#include "logging.h" #include "application.h" #include "applicationinstaller.h" #include "applicationinstaller_p.h" diff --git a/src/installer-lib/deinstallationtask.cpp b/src/installer-lib/deinstallationtask.cpp index 6dc917dc..e4a429cf 100644 --- a/src/installer-lib/deinstallationtask.cpp +++ b/src/installer-lib/deinstallationtask.cpp @@ -39,6 +39,7 @@ ** ****************************************************************************/ +#include "logging.h" #include "applicationinstaller.h" #include "applicationinstaller_p.h" #include "applicationmanager.h" diff --git a/src/installer-lib/installationtask.cpp b/src/installer-lib/installationtask.cpp index 008da8e0..2adf827d 100644 --- a/src/installer-lib/installationtask.cpp +++ b/src/installer-lib/installationtask.cpp @@ -39,6 +39,7 @@ ** ****************************************************************************/ +#include "logging.h" #include "applicationinstaller_p.h" #include "application.h" #include "packageextractor.h" diff --git a/src/installer-lib/scopeutilities.cpp b/src/installer-lib/scopeutilities.cpp index 9e8012ea..312bfb3b 100644 --- a/src/installer-lib/scopeutilities.cpp +++ b/src/installer-lib/scopeutilities.cpp @@ -39,6 +39,7 @@ ** ****************************************************************************/ +#include "logging.h" #include "scopeutilities.h" #include "applicationinstaller_p.h" #include "utilities.h" diff --git a/src/installer-lib/sudo.cpp b/src/installer-lib/sudo.cpp index cec70692..34b093da 100644 --- a/src/installer-lib/sudo.cpp +++ b/src/installer-lib/sudo.cpp @@ -48,6 +48,7 @@ #include <qplatformdefs.h> #include <QDataStream> +#include "logging.h" #include "sudo.h" #include "utilities.h" #include "exception.h" diff --git a/src/launcher-lib/applicationmanagerwindow.cpp b/src/launcher-lib/applicationmanagerwindow.cpp index 98380517..4de5aca6 100644 --- a/src/launcher-lib/applicationmanagerwindow.cpp +++ b/src/launcher-lib/applicationmanagerwindow.cpp @@ -44,6 +44,7 @@ #include <qpa/qplatformnativeinterface.h> #include <qpa/qplatformwindow.h> +#include "logging.h" #include "applicationmanagerwindow_p.h" QT_BEGIN_NAMESPACE_AM diff --git a/src/launcher-lib/qmlapplicationinterfaceextension.cpp b/src/launcher-lib/qmlapplicationinterfaceextension.cpp index e853acc0..86dad19d 100644 --- a/src/launcher-lib/qmlapplicationinterfaceextension.cpp +++ b/src/launcher-lib/qmlapplicationinterfaceextension.cpp @@ -41,6 +41,7 @@ #include <QDBusInterface> +#include "logging.h" #include "qmlapplicationinterfaceextension.h" #include "qmlapplicationinterface.h" #include "ipcwrapperobject.h" diff --git a/src/launchers/qml/main.cpp b/src/launchers/qml/main.cpp index fa4e0ef2..0f8412bb 100644 --- a/src/launchers/qml/main.cpp +++ b/src/launchers/qml/main.cpp @@ -79,7 +79,9 @@ #include "notification.h" #include "qtyaml.h" #include "global.h" +#include "logging.h" #include "utilities.h" +#include "crashhandler.h" #include "yamlapplicationscanner.h" #include "application.h" #include "startupinterface.h" @@ -174,7 +176,7 @@ int main(int argc, char *argv[]) StartupTimer::instance()->checkpoint("entered main"); if (qEnvironmentVariableIsSet("AM_NO_DLT_LOGGING")) - dltLoggingEnabled = false; + Logging::setDltEnabled(false); // The common-lib is already registering the DLT Application for the application manager. // As the appID needs to be unique within the system, we cannot use the same appID and @@ -182,10 +184,10 @@ int main(int argc, char *argv[]) // As we don't know the app-id yet, we are registering a place holder so we are able to see // something in the dlt logs if general errors occur. - changeDLTApplication("PCLQ", "Pelagicore Application-Manager Launcher QML"); + Logging::setDltApplicationId("PCLQ", "Pelagicore Application-Manager Launcher QML"); + Logging::setApplicationId("qml-launcher"); + Logging::initialize(); - colorLogApplicationId = "qml-launcher"; - installMessageHandlers(); QLoggingCategory::setFilterRules(QString::fromUtf8(qgetenv("AM_LOGGING_RULES"))); #if defined(AM_HEADLESS) @@ -276,7 +278,7 @@ Controller::Controller(QCoreApplication *a, const QString &directLoad) if (docs.size() == 1) m_configuration = docs.first().toMap(); - setCrashActionConfiguration(m_configuration.value(qSL("crashAction")).toMap()); + CrashHandler::setCrashActionConfiguration(m_configuration.value(qSL("crashAction")).toMap()); const QString baseDir = QString::fromLocal8Bit(qgetenv("AM_BASE_DIR") + "/"); @@ -364,8 +366,8 @@ void Controller::startApplication(const QString &baseDir, const QString &qmlFile //Change the DLT Application description, to easily identify the application on the DLT logs. char dltAppId[5]; qsnprintf(dltAppId, 5, "A%03d", application.value("uniqueNumber").toInt()); - changeDLTApplication(dltAppId, QString("Application-Manager App: %1").arg(applicationId).toLocal8Bit()); - registerUnregisteredDLTContexts(); + Logging::setDltApplicationId(dltAppId, QByteArray("Application-Manager App: ") + applicationId.toLocal8Bit()); + Logging::registerUnregisteredDltContexts(); // Dress up the ps output to make it easier to correlate all the launcher processes { @@ -396,7 +398,7 @@ void Controller::startApplication(const QString &baseDir, const QString &qmlFile applicationId.append(qL1C('.')); } applicationId.append(sl.last()); - colorLogApplicationId = applicationId.toLocal8Bit(); + Logging::setApplicationId(applicationId.toLocal8Bit()); } else { qCCritical(LogQmlRuntime) << "did not receive an application id"; QCoreApplication::exit(2); diff --git a/src/manager-lib/abstractcontainer.h b/src/manager-lib/abstractcontainer.h index feac1f82..d97be936 100644 --- a/src/manager-lib/abstractcontainer.h +++ b/src/manager-lib/abstractcontainer.h @@ -44,7 +44,8 @@ #include <QObject> #include <QString> #include <QProcess> -#include <QDir> +#include <QVariantMap> +#include <QVector> #include <QtAppManCommon/global.h> diff --git a/src/manager-lib/abstractruntime.cpp b/src/manager-lib/abstractruntime.cpp index 6eb95b34..5a6137ad 100644 --- a/src/manager-lib/abstractruntime.cpp +++ b/src/manager-lib/abstractruntime.cpp @@ -40,6 +40,7 @@ ****************************************************************************/ #include "global.h" +#include "logging.h" #include "application.h" #include "abstractruntime.h" #include "abstractcontainer.h" diff --git a/src/manager-lib/abstractruntime.h b/src/manager-lib/abstractruntime.h index 8812f608..2d37bc4c 100644 --- a/src/manager-lib/abstractruntime.h +++ b/src/manager-lib/abstractruntime.h @@ -45,6 +45,7 @@ #include <QString> #include <QProcess> #include <QPointer> +#include <QVariantMap> #include <QtAppManCommon/global.h> diff --git a/src/manager-lib/applicationipcinterface.cpp b/src/manager-lib/applicationipcinterface.cpp index 3c39b88a..98a7db35 100644 --- a/src/manager-lib/applicationipcinterface.cpp +++ b/src/manager-lib/applicationipcinterface.cpp @@ -54,6 +54,7 @@ #include <QDebug> +#include "logging.h" #include "application.h" #include "utilities.h" #include "dbus-utilities.h" diff --git a/src/manager-lib/applicationipcmanager.cpp b/src/manager-lib/applicationipcmanager.cpp index 59ec1a02..1b681a74 100644 --- a/src/manager-lib/applicationipcmanager.cpp +++ b/src/manager-lib/applicationipcmanager.cpp @@ -44,6 +44,7 @@ #include "applicationipcinterface_p.h" #include "qml-utilities.h" #include "global.h" +#include "logging.h" /*! diff --git a/src/manager-lib/applicationmanager.cpp b/src/manager-lib/applicationmanager.cpp index 93e09f0a..4e8dfc12 100644 --- a/src/manager-lib/applicationmanager.cpp +++ b/src/manager-lib/applicationmanager.cpp @@ -53,7 +53,7 @@ #include <qplatformdefs.h> #include "global.h" - +#include "logging.h" #include "applicationdatabase.h" #include "applicationmanager.h" #include "applicationmanager_p.h" diff --git a/src/manager-lib/containerfactory.cpp b/src/manager-lib/containerfactory.cpp index 8b8eeb11..08e55a35 100644 --- a/src/manager-lib/containerfactory.cpp +++ b/src/manager-lib/containerfactory.cpp @@ -43,6 +43,7 @@ #include <QCoreApplication> #include <QThreadPool> +#include "logging.h" #include "application.h" #include "abstractruntime.h" #include "abstractcontainer.h" diff --git a/src/manager-lib/containerfactory.h b/src/manager-lib/containerfactory.h index 58da8e01..19287646 100644 --- a/src/manager-lib/containerfactory.h +++ b/src/manager-lib/containerfactory.h @@ -43,7 +43,7 @@ #include <QMap> #include <QObject> - +#include <QVector> #include <QtAppManCommon/global.h> QT_BEGIN_NAMESPACE_AM diff --git a/src/manager-lib/fakeapplicationmanagerwindow.cpp b/src/manager-lib/fakeapplicationmanagerwindow.cpp index ae5de0fd..b328d951 100644 --- a/src/manager-lib/fakeapplicationmanagerwindow.cpp +++ b/src/manager-lib/fakeapplicationmanagerwindow.cpp @@ -39,6 +39,7 @@ ** ****************************************************************************/ +#include "logging.h" #include "fakeapplicationmanagerwindow.h" #include "qmlinprocessruntime.h" #include <QSGSimpleRectNode> diff --git a/src/manager-lib/memorymonitor.cpp b/src/manager-lib/memorymonitor.cpp index 2d8c9f7c..712e6f94 100644 --- a/src/manager-lib/memorymonitor.cpp +++ b/src/manager-lib/memorymonitor.cpp @@ -43,6 +43,7 @@ #include <QFile> #include <QVector> #include "global.h" +#include "logging.h" #include "memorymonitor.h" #if defined(Q_OS_OSX) diff --git a/src/manager-lib/nativeruntime.cpp b/src/manager-lib/nativeruntime.cpp index 87782fd6..7823a478 100644 --- a/src/manager-lib/nativeruntime.cpp +++ b/src/manager-lib/nativeruntime.cpp @@ -48,6 +48,7 @@ #include <QUuid> #include "global.h" +#include "logging.h" #include "application.h" #include "applicationmanager.h" #include "nativeruntime.h" @@ -200,7 +201,7 @@ bool NativeRuntime::start() if (!m_needsLauncher && !m_isQuickLauncher) env.insert(qSL("AM_RUNTIME_SYSTEM_PROPERTIES"), QString::fromUtf8(QtYaml::yamlFromVariantDocuments({ systemProperties() }))); env.insert(qSL("AM_BASE_DIR"), QDir::currentPath()); - if (!dltLoggingEnabled) + if (Logging::isDltEnabled()) env.insert(qSL("AM_NO_DLT_LOGGING"), qSL("1")); for (QMapIterator<QString, QVariant> it(configuration().value(qSL("environmentVariables")).toMap()); it.hasNext(); ) { diff --git a/src/manager-lib/nativeruntime.h b/src/manager-lib/nativeruntime.h index da017cdf..f3dd515f 100644 --- a/src/manager-lib/nativeruntime.h +++ b/src/manager-lib/nativeruntime.h @@ -47,6 +47,7 @@ #include <QtPlugin> #include <QProcess> +#include <QVector> #include <QtAppManManager/abstractruntime.h> #include <QtAppManManager/abstractcontainer.h> diff --git a/src/manager-lib/notificationmanager.cpp b/src/manager-lib/notificationmanager.cpp index bf891aeb..7689aa0c 100644 --- a/src/manager-lib/notificationmanager.cpp +++ b/src/manager-lib/notificationmanager.cpp @@ -44,7 +44,7 @@ #include <QTimer> #include "global.h" - +#include "logging.h" #include "application.h" #include "applicationmanager.h" #include "notificationmanager.h" diff --git a/src/manager-lib/processcontainer.cpp b/src/manager-lib/processcontainer.cpp index 3ff1d805..42a64dc8 100644 --- a/src/manager-lib/processcontainer.cpp +++ b/src/manager-lib/processcontainer.cpp @@ -40,6 +40,7 @@ ****************************************************************************/ #include "global.h" +#include "logging.h" #include "containerfactory.h" #include "application.h" #include "processcontainer.h" diff --git a/src/manager-lib/processmonitor.cpp b/src/manager-lib/processmonitor.cpp index 38fc40ec..71b97802 100644 --- a/src/manager-lib/processmonitor.cpp +++ b/src/manager-lib/processmonitor.cpp @@ -41,6 +41,7 @@ #include <QDebug> #include <QCoreApplication> +#include "logging.h" #include "processmonitor.h" #include "memorymonitor.h" #include "application.h" diff --git a/src/manager-lib/qmlinprocessapplicationinterface.cpp b/src/manager-lib/qmlinprocessapplicationinterface.cpp index b4b07daa..6b4bb4a2 100644 --- a/src/manager-lib/qmlinprocessapplicationinterface.cpp +++ b/src/manager-lib/qmlinprocessapplicationinterface.cpp @@ -42,6 +42,7 @@ #include <QQmlEngine> #include <QQmlExpression> +#include "logging.h" #include "qmlinprocessapplicationinterface.h" #include "qmlinprocessruntime.h" #include "application.h" diff --git a/src/manager-lib/qmlinprocessruntime.cpp b/src/manager-lib/qmlinprocessruntime.cpp index ca650e27..2fb02bbb 100644 --- a/src/manager-lib/qmlinprocessruntime.cpp +++ b/src/manager-lib/qmlinprocessruntime.cpp @@ -51,6 +51,7 @@ # include "fakeapplicationmanagerwindow.h" #endif +#include "logging.h" #include "application.h" #include "qmlinprocessruntime.h" #include "qmlinprocessapplicationinterface.h" diff --git a/src/manager-lib/quicklauncher.cpp b/src/manager-lib/quicklauncher.cpp index 5fbfc5ae..cd719ab5 100644 --- a/src/manager-lib/quicklauncher.cpp +++ b/src/manager-lib/quicklauncher.cpp @@ -42,6 +42,7 @@ #include <QCoreApplication> #include <QTimer> +#include "logging.h" #include "abstractcontainer.h" #include "abstractruntime.h" #include "containerfactory.h" diff --git a/src/manager-lib/runtimefactory.cpp b/src/manager-lib/runtimefactory.cpp index 89d77b7e..0fd009cb 100644 --- a/src/manager-lib/runtimefactory.cpp +++ b/src/manager-lib/runtimefactory.cpp @@ -42,6 +42,7 @@ #include <QScopedPointer> #include <QCoreApplication> +#include "logging.h" #include "application.h" #include "abstractruntime.h" #include "abstractcontainer.h" diff --git a/src/manager-lib/systemmonitor.cpp b/src/manager-lib/systemmonitor.cpp index 9b6d6704..e737243b 100644 --- a/src/manager-lib/systemmonitor.cpp +++ b/src/manager-lib/systemmonitor.cpp @@ -48,15 +48,14 @@ #include <vector> #include <QGuiApplication> +#include "global.h" +#include "logging.h" +#include "qml-utilities.h" #include "applicationmanager.h" #include "systemmonitor.h" #include "systemmonitor_p.h" #include "processmonitor.h" -#include "global.h" - -#include "qml-utilities.h" - /*! \qmltype SystemMonitor diff --git a/src/manager-lib/systemmonitor_p.cpp b/src/manager-lib/systemmonitor_p.cpp index 60685fde..49a73af5 100644 --- a/src/manager-lib/systemmonitor_p.cpp +++ b/src/manager-lib/systemmonitor_p.cpp @@ -43,6 +43,7 @@ #include "systemmonitor_p.h" #include "global.h" +#include "logging.h" QT_BEGIN_NAMESPACE_AM diff --git a/src/manager/configuration.cpp b/src/manager/configuration.cpp index e13eab1c..ffb8d092 100644 --- a/src/manager/configuration.cpp +++ b/src/manager/configuration.cpp @@ -47,6 +47,7 @@ #include <functional> #include "global.h" +#include "logging.h" #include "qtyaml.h" #include "utilities.h" #include "configuration.h" diff --git a/src/manager/main.cpp b/src/manager/main.cpp index 956795b8..7618b6e1 100644 --- a/src/manager/main.cpp +++ b/src/manager/main.cpp @@ -83,7 +83,7 @@ #endif #include "global.h" - +#include "logging.h" #include "application.h" #include "applicationmanager.h" #include "applicationdatabase.h" @@ -120,6 +120,7 @@ #include "configuration.h" #include "utilities.h" +#include "crashhandler.h" #include "qmllogger.h" #include "startuptimer.h" #include "systemmonitor.h" @@ -502,11 +503,11 @@ int main(int argc, char *argv[]) QCoreApplication::setApplicationVersion(qSL(AM_VERSION)); for (int i = 1; i < argc; ++i) { if (strcmp("--no-dlt-logging", argv[i]) == 0) { - dltLoggingEnabled = false; + Logging::setDltEnabled(false); break; } } - installMessageHandlers(); + Logging::initialize(); QString error; @@ -552,7 +553,7 @@ int main(int argc, char *argv[]) StartupTimer::instance()->checkpoint("after command line parse"); - setCrashActionConfiguration(configuration->managerCrashAction()); + CrashHandler::setCrashActionConfiguration(configuration->managerCrashAction()); #if !defined(QT_NO_QML_DEBUGGER) QQmlDebuggingEnabler *debuggingEnabler = nullptr; @@ -584,7 +585,7 @@ int main(int argc, char *argv[]) // setting this for child processes //TODO: use a more generic IPC approach qputenv("AM_LOGGING_RULES", loggingRules.join(qL1C('\n')).toUtf8()); - registerUnregisteredDLTContexts(); + Logging::registerUnregisteredDltContexts(); StartupTimer::instance()->checkpoint("after logging setup"); diff --git a/src/manager/qmllogger.cpp b/src/manager/qmllogger.cpp index bb4f275b..4c8a703b 100644 --- a/src/manager/qmllogger.cpp +++ b/src/manager/qmllogger.cpp @@ -43,6 +43,7 @@ #include "qmllogger.h" #include "global.h" +#include "logging.h" QT_BEGIN_NAMESPACE_AM diff --git a/src/tools/testrunner/testrunner.h b/src/tools/testrunner/testrunner.h index 4e3a4fe4..9199bae8 100644 --- a/src/tools/testrunner/testrunner.h +++ b/src/tools/testrunner/testrunner.h @@ -44,6 +44,7 @@ #include <QtAppManCommon/global.h> QT_FORWARD_DECLARE_CLASS(QQmlEngine) +QT_FORWARD_DECLARE_CLASS(QStringList) QT_BEGIN_NAMESPACE_AM diff --git a/src/window-lib/waylandcompositor.cpp b/src/window-lib/waylandcompositor.cpp index e16eca5c..10c47291 100644 --- a/src/window-lib/waylandcompositor.cpp +++ b/src/window-lib/waylandcompositor.cpp @@ -44,6 +44,7 @@ #include <QWaylandOutput> #include "global.h" +#include "logging.h" #include "windowmanager.h" #include "application.h" #include "applicationmanager.h" diff --git a/src/window-lib/waylandwindow.cpp b/src/window-lib/waylandwindow.cpp index a54c40b1..4d7e7bed 100644 --- a/src/window-lib/waylandwindow.cpp +++ b/src/window-lib/waylandwindow.cpp @@ -42,6 +42,7 @@ #if defined(AM_MULTI_PROCESS) #include "global.h" +#include "logging.h" #include "applicationmanager.h" #include "application.h" #include "windowmanager.h" diff --git a/src/window-lib/windowmanager.cpp b/src/window-lib/windowmanager.cpp index eabf95af..900326c0 100644 --- a/src/window-lib/windowmanager.cpp +++ b/src/window-lib/windowmanager.cpp @@ -57,6 +57,7 @@ #endif #include "global.h" +#include "logging.h" #include "application.h" #include "applicationmanager.h" #include "abstractruntime.h" |