File indexing completed on 2024-05-19 04:25:03

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 abort, 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     // or if the GUI is not yet instantiated
0060     if (!QCoreApplication::instance() || QThread::currentThread() != QCoreApplication::instance()->thread()) {
0061         disableAssertMsg = true;
0062     }
0063 
0064     bool shouldIgnoreAsserts = false;
0065     bool forceCrashOnSafeAsserts = false;
0066 
0067 #ifdef HIDE_SAFE_ASSERTS
0068     shouldIgnoreAsserts |= HIDE_SAFE_ASSERTS;
0069 #endif
0070 
0071 #ifdef CRASH_ON_SAFE_ASSERTS
0072     forceCrashOnSafeAsserts |= CRASH_ON_SAFE_ASSERTS;
0073 #endif
0074 
0075     disableAssertMsg |= shouldIgnoreAsserts || forceCrashOnSafeAsserts;
0076 
0077     QMessageBox::StandardButton button =
0078         isIgnorable && !forceCrashOnSafeAsserts ?
0079             QMessageBox::Ignore : QMessageBox::Abort;
0080 
0081     if (!disableAssertMsg) {
0082         button =
0083             QMessageBox::critical(qApp->activeWindow(), i18nc("@title:window", "Krita: Internal Error"),
0084                                   longMessage,
0085                                   QMessageBox::Ignore | QMessageBox::Abort,
0086                                   QMessageBox::Ignore);
0087     }
0088 
0089     if (button == QMessageBox::Abort || abort) {
0090         qFatal("%s", shortMessage.toLatin1().data());
0091     } else if (isIgnorable) {
0092         // Assert is a bug! Please don't change this line to warnKrita,
0093         // the user must see it!
0094         qWarning("%s", shortMessage.toLatin1().data());
0095     }
0096 }
0097 
0098 
0099 void kis_assert_recoverable(const char *assertion, const char *file, int line)
0100 {
0101     kis_assert_common(assertion, file, line, false, false);
0102 }
0103 
0104 void kis_safe_assert_recoverable(const char *assertion, const char *file, int line)
0105 {
0106     kis_assert_common(assertion, file, line, false, true);
0107 }
0108 
0109 void kis_assert_exception(const char *assertion, const char *file, int line)
0110 {
0111     kis_assert_common(assertion, file, line, true, false);
0112 }
0113 
0114 void kis_assert_x_exception(const char *assertion,
0115                             const char *where,
0116                             const char *what,
0117                             const char *file, int line)
0118 {
0119     QString res =
0120         QString("ASSERT failure in %1: \"%2\" (%3)")
0121         .arg(where, what, assertion);
0122 
0123     kis_assert_common(res.toLatin1().data(), file, line, true, false);
0124 }