File indexing completed on 2024-05-12 15:56:57

0001 /*
0002  *  SPDX-FileCopyrightText: 2013 Dmitry Kazakov <dimula73@gmail.com>
0003  *
0004  *  SPDX-License-Identifier: GPL-2.0-or-later
0005  */
0006 
0007 #include "kis_assert.h"
0008 
0009 #include <QString>
0010 #include <QMessageBox>
0011 #include <QThread>
0012 #include <QProcessEnvironment>
0013 #include <QCoreApplication>
0014 #include <QApplication>
0015 
0016 #include <klocalizedstring.h>
0017 #include <kis_assert_exception.h>
0018 #include <KisUsageLogger.h>
0019 #include <string>
0020 #include "config-safe-asserts.h"
0021 
0022 /**
0023  * TODO: Add automatic saving of the documents
0024  *
0025  * Requirements:
0026  * 1) Should save all open KisDocument objects
0027  * 2) Should *not* overwrite original document since the saving
0028  *    process may fail.
0029  * 3) Should *not* overwrite any autosaved documents since the saving
0030  *    process may fail.
0031  * 4) Double-fault tolerance! Assert during emergency saving should not
0032  *    lead to an infinite loop.
0033  */
0034 
0035 void kis_assert_common(const char *assertion, const char *file, int line, bool throwException, bool isIgnorable)
0036 {
0037     QString shortMessage =
0038         QString("%4ASSERT (krita): \"%1\" in file %2, line %3")
0039         .arg(assertion)
0040         .arg(file)
0041         .arg(line)
0042         .arg(isIgnorable ? "SAFE " : "");
0043 
0044     QString longMessage =
0045         QString(
0046             "Krita has encountered an internal error:\n\n"
0047             "%1\n\n"
0048             "Please report a bug to developers!\n\n"
0049             "Press Ignore to try to continue.\n"
0050             "Press Abort to see developers information (all unsaved data will be lost)")
0051         .arg(shortMessage);
0052 
0053     KisUsageLogger::log(shortMessage);
0054 
0055     bool disableAssertMsg =
0056         QProcessEnvironment::systemEnvironment().value("KRITA_NO_ASSERT_MSG", "0").toInt();
0057 
0058     // disable message box if the assert happened in non-gui thread :(
0059     if (QThread::currentThread() != QCoreApplication::instance()->thread()) {
0060         disableAssertMsg = true;
0061     }
0062 
0063     bool shouldIgnoreAsserts = false;
0064     bool forceCrashOnSafeAsserts = false;
0065 
0066 #ifdef HIDE_SAFE_ASSERTS
0067     shouldIgnoreAsserts |= HIDE_SAFE_ASSERTS;
0068 #endif
0069 
0070 #ifdef CRASH_ON_SAFE_ASSERTS
0071     forceCrashOnSafeAsserts |= CRASH_ON_SAFE_ASSERTS;
0072 #endif
0073 
0074     disableAssertMsg |= shouldIgnoreAsserts || forceCrashOnSafeAsserts;
0075 
0076     QMessageBox::StandardButton button =
0077         isIgnorable && !forceCrashOnSafeAsserts ?
0078             QMessageBox::Ignore : QMessageBox::Abort;
0079 
0080     if (!disableAssertMsg) {
0081         button =
0082             QMessageBox::critical(qApp->activeWindow(), i18nc("@title:window", "Krita: Internal Error"),
0083                                   longMessage,
0084                                   QMessageBox::Ignore | QMessageBox::Abort,
0085                                   QMessageBox::Ignore);
0086     }
0087 
0088     if (button == QMessageBox::Abort) {
0089         qFatal("%s", shortMessage.toLatin1().data());
0090     } else if (isIgnorable) {
0091         // Assert is a bug! Please don't change this line to warnKrita,
0092         // the user must see it!
0093         qWarning("%s", shortMessage.toLatin1().data());
0094     } else if (throwException) {
0095         throw KisAssertException(shortMessage.toLatin1().data());
0096     }
0097 }
0098 
0099 
0100 void kis_assert_recoverable(const char *assertion, const char *file, int line)
0101 {
0102     kis_assert_common(assertion, file, line, false, false);
0103 }
0104 
0105 void kis_safe_assert_recoverable(const char *assertion, const char *file, int line)
0106 {
0107     kis_assert_common(assertion, file, line, false, true);
0108 }
0109 
0110 void kis_assert_exception(const char *assertion, const char *file, int line)
0111 {
0112     kis_assert_common(assertion, file, line, true, false);
0113 }
0114 
0115 void kis_assert_x_exception(const char *assertion,
0116                             const char *where,
0117                             const char *what,
0118                             const char *file, int line)
0119 {
0120     QString res =
0121         QString("ASSERT failure in %1: \"%2\" (%3)")
0122         .arg(where, what, assertion);
0123 
0124     kis_assert_common(res.toLatin1().data(), file, line, true, false);
0125 }