File indexing completed on 2024-05-19 04:23:46

0001 // SPDX-FileCopyrightText: 2021 Johannes Zarl-Zierl <johannes@zarl-zierl.at>
0002 // SPDX-FileCopyrightText: 2022 Johannes Zarl-Zierl <johannes@zarl-zierl.at>
0003 //
0004 // SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
0005 
0006 #ifndef KPABASE_CRASH_SENTINEL_H
0007 #define KPABASE_CRASH_SENTINEL_H
0008 
0009 #include <QByteArray>
0010 #include <QList>
0011 #include <QString>
0012 
0013 namespace KPABase
0014 {
0015 
0016 /**
0017  * @brief The CrashSentinel class acts as a memento as to what KPhotoAlbum was doing when a crash occurs.
0018  * The intention is to use this when using external libraries that are known to crash sometimes and that are outside of our control.
0019  *
0020  * The CrashSentinel was introduced to be able to react to some video backends crashing for some users.
0021  * If the app knows that a video was playing when while it exited anomally, it can try a different backend next time.
0022  *
0023  * The sentinel writes the crashInfo into the \c component configuration of the `[CrashInfo]` section of the application configuration file.
0024  * Calling activate() (re)enables the crash detection.
0025  * When the CrashSentinel is deleted or if suspend() is called, the crashInfo is removed.
0026  *
0027  * You should never create more than one CrashSentinel for the same component: the sentinel assumes exclusive access to the associated config entries.
0028  */
0029 class CrashSentinel
0030 {
0031 public:
0032     /**
0033      * @brief Create a CrashSentinel for the given component.
0034      * @param component the name of the component that is covered by the CrashSentinel
0035      * @param crashInfo the identifier of the currently active code path
0036      */
0037     explicit CrashSentinel(const QString &component, const QByteArray &crashInfo = QByteArray());
0038     ~CrashSentinel();
0039 
0040     /**
0041      * @brief hasCrashInfo
0042      * @return \c true, if there was a crash info upon initialization of the sentinel, \c false if not.
0043      */
0044     bool hasCrashInfo() const;
0045     /**
0046      * @brief lastCrashInfo
0047      * @return the crash information from the last crash, or an empty string if hasCrashInfo() is false.
0048      */
0049     QByteArray lastCrashInfo() const;
0050 
0051     /**
0052      * @brief crashHistory
0053      * @return a list of all previously recorded crash infos (including the lastCrashInfo)
0054      */
0055     QList<QByteArray> crashHistory() const;
0056 
0057     /**
0058      * @brief clearCrashHistory clears all previously recorded crash infos.
0059      * The information returned by hasCrashInfo() and lastCrashInfo() is not affected.
0060      */
0061     void clearCrashHistory();
0062 
0063     /**
0064      * @brief setCrashInfo replaces the crashInfo with a new identifier.
0065      * Setting the crashInfo does not affect whether the sentinel is suspended or not.
0066      */
0067     void setCrashInfo(const QByteArray &crashInfo);
0068 
0069     /**
0070      * @brief component
0071      * @return the component name.
0072      */
0073     QString component() const;
0074 
0075     /**
0076      * @brief crashInfo
0077      * @return the active crashInfo identifier.
0078      */
0079     QByteArray crashInfo() const;
0080 
0081     /**
0082      * @brief isSuspended
0083      * @return \c true, if the sentinel is currently suspended, \c false otherwise
0084      */
0085     bool isSuspended() const;
0086 
0087     /**
0088      * @brief suspend the CrashSentinel.
0089      * While suspended, the sentinel will not be able to register a crash.
0090      * Call this, if the "crashy" component is unlikely to actually crash, e.g. when the component is still loaded in memory but not doing anything.
0091      * This allows you to avoid false positives because of the application crashing in another component.
0092      * Calling suspend on an already suspended CrashSentinel will do nothing.
0093      */
0094     void suspend();
0095 
0096     /**
0097      * @brief activate the CrashSentinel if it is suspended.
0098      * Calling activate on a non-suspended CrashSentinel will do nothing.
0099      */
0100     void activate();
0101 
0102     /**
0103      * @brief disablePermanently disabled the CrashSentinel permanently.
0104      * I.e. crash data will still be stored, but no indication of any crash will be shown by any of the methods
0105      * hasCrashInfo(), lastCrashInfo(), crashHistory().
0106      * To reenable, call clearCrashHistory();
0107      *
0108      * Use this method if an crashes are spurious and should be ignored.
0109      */
0110     void disablePermanently();
0111 
0112     /**
0113      * @brief isDisabled
0114      * @return \c true, if the crash sentinel was permanently disabled, \c false otherwise.
0115      */
0116     bool isDisabled() const;
0117 
0118 private:
0119     const QString m_component;
0120     QByteArray m_crashInfo;
0121     QByteArray m_lastCrashInfo;
0122 };
0123 
0124 }
0125 
0126 #endif // KPABASE_CRASH_SENTINEL_H
0127 // vi:expandtab:tabstop=4 shiftwidth=4: