File indexing completed on 2024-06-16 04:50:02

0001 /***************************************************************************
0002  *   SPDX-FileCopyrightText: 2006 Tobias Koenig <tokoe@kde.org>            *
0003  *                                                                         *
0004  *   SPDX-License-Identifier: LGPL-2.0-or-later                            *
0005  ***************************************************************************/
0006 
0007 #pragma once
0008 
0009 #include <QObject>
0010 #include <QProcess>
0011 
0012 #include <chrono>
0013 
0014 namespace Akonadi
0015 {
0016 /**
0017  * This class starts and observes a process. Depending on the
0018  * policy it also restarts the process when it crashes.
0019  */
0020 class ProcessControl : public QObject
0021 {
0022     Q_OBJECT
0023 
0024 public:
0025     /**
0026      * These enums describe the behaviour when the observed
0027      * application crashed.
0028      *
0029      * @li StopOnCrash    - The application won't be restarted.
0030      * @li RestartOnCrash - The application is restarted with the same arguments.
0031      */
0032     enum CrashPolicy {
0033         StopOnCrash,
0034         RestartOnCrash,
0035     };
0036 
0037     /**
0038      * Creates a new process control.
0039      *
0040      * @param parent The parent object.
0041      */
0042     explicit ProcessControl(QObject *parent = nullptr);
0043 
0044     /**
0045      * Destroys the process control.
0046      */
0047     ~ProcessControl() override;
0048 
0049     /**
0050      * Starts the @p application with the given list of @p arguments.
0051      */
0052     void start(const QString &application, const QStringList &arguments = QStringList(), CrashPolicy policy = RestartOnCrash);
0053 
0054     /**
0055      * Starts the process with the previously set application and arguments.
0056      */
0057     void start();
0058 
0059     /**
0060      * Stops the currently running application.
0061      */
0062     void stop();
0063 
0064     /**
0065      * Sets the crash policy.
0066      */
0067     void setCrashPolicy(CrashPolicy policy);
0068 
0069     /**
0070      * Restart the application the next time it exits normally.
0071      */
0072     void restartOnceWhenFinished()
0073     {
0074         mRestartOnceOnExit = true;
0075     }
0076 
0077     /**
0078      * Returns true if the process is currently running.
0079      */
0080     [[nodiscard]] bool isRunning() const;
0081 
0082     /**
0083      * Sets the time (in msecs) we wait for the process to shut down before we send terminate/kill signals.
0084      * Default is 1 second.
0085      * Note that it is your responsiblility to ask the process to quit, otherwise this is just
0086      * pointless waiting.
0087      */
0088     void setShutdownTimeout(std::chrono::milliseconds timeout);
0089 
0090 Q_SIGNALS:
0091     /**
0092      * This signal is emitted whenever the observed application
0093      * writes something to stderr.
0094      *
0095      * @param errorMsg The error output of the observed application.
0096      */
0097     void processErrorMessages(const QString &errorMsg);
0098 
0099     /**
0100      * This signal is emitted when the server is restarted after a crash.
0101      */
0102     void restarted();
0103 
0104     /**
0105      * Emitted if the process could not be started since it terminated
0106      * too often.
0107      */
0108     void unableToStart();
0109 
0110 private Q_SLOTS:
0111     void slotError(QProcess::ProcessError);
0112     void slotFinished(int, QProcess::ExitStatus);
0113     void resetCrashCount();
0114 
0115 private:
0116     QProcess mProcess;
0117     QString mApplication;
0118     QStringList mArguments;
0119     CrashPolicy mPolicy = RestartOnCrash;
0120     bool mFailedToStart = false;
0121     int mCrashCount = 0;
0122     bool mRestartOnceOnExit = false;
0123     std::chrono::milliseconds mShutdownTimeout;
0124 };
0125 
0126 }