2022-08-19 15:59:36 +02:00
|
|
|
// Copyright (C) 2016 The Qt Company Ltd.
|
2022-12-21 10:12:09 +01:00
|
|
|
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
|
2010-10-14 18:05:43 +02:00
|
|
|
|
2023-05-04 15:07:18 +02:00
|
|
|
#if defined(Q_CC_MINGW) && defined(WIN_PTHREADS_H) && !defined(_INC_PROCESS)
|
|
|
|
|
// Arrived here via <pthread.h> which wants to include <process.h>
|
|
|
|
|
#include_next <process.h>
|
|
|
|
|
#elif !defined(UTILS_PROCESS_H)
|
|
|
|
|
#define UTILS_PROCESS_H
|
2010-10-14 18:05:43 +02:00
|
|
|
|
2021-05-05 18:21:22 +02:00
|
|
|
#include "utils_global.h"
|
|
|
|
|
|
2021-05-11 14:34:56 +02:00
|
|
|
#include "commandline.h"
|
2022-02-18 00:56:14 +01:00
|
|
|
#include "processenums.h"
|
2022-10-12 14:30:24 +02:00
|
|
|
#include "tasktree.h"
|
2010-10-14 18:05:43 +02:00
|
|
|
|
2013-03-18 14:47:33 +01:00
|
|
|
#include <QProcess>
|
2021-05-05 18:21:22 +02:00
|
|
|
|
2022-03-29 18:01:08 +02:00
|
|
|
QT_BEGIN_NAMESPACE
|
|
|
|
|
class QDebug;
|
|
|
|
|
class QTextCodec;
|
|
|
|
|
QT_END_NAMESPACE
|
2013-03-18 14:47:33 +01:00
|
|
|
|
2010-10-14 18:05:43 +02:00
|
|
|
namespace Utils {
|
2021-05-05 18:21:22 +02:00
|
|
|
|
2021-05-06 11:15:28 +02:00
|
|
|
namespace Internal { class QtcProcessPrivate; }
|
2023-03-02 14:03:54 +01:00
|
|
|
namespace Pty { class Data; }
|
2021-05-06 11:15:28 +02:00
|
|
|
|
2022-05-06 12:42:03 +02:00
|
|
|
class Environment;
|
2022-02-18 01:53:33 +01:00
|
|
|
class DeviceProcessHooks;
|
2022-03-29 18:01:08 +02:00
|
|
|
class ProcessInterface;
|
2022-04-08 17:24:59 +02:00
|
|
|
class ProcessResultData;
|
2022-02-18 01:53:33 +01:00
|
|
|
|
2023-05-03 16:00:22 +02:00
|
|
|
class QTCREATOR_UTILS_EXPORT Process final : public QObject
|
2021-05-05 18:21:22 +02:00
|
|
|
{
|
2021-05-12 14:25:50 +02:00
|
|
|
Q_OBJECT
|
|
|
|
|
|
2021-05-05 18:21:22 +02:00
|
|
|
public:
|
2023-05-03 16:00:22 +02:00
|
|
|
explicit Process(QObject *parent = nullptr);
|
|
|
|
|
~Process();
|
2022-02-10 19:25:03 +01:00
|
|
|
|
2022-02-17 23:25:54 +01:00
|
|
|
// ProcessInterface related
|
|
|
|
|
|
2022-04-12 11:18:09 +02:00
|
|
|
void start();
|
2022-04-11 19:45:04 +02:00
|
|
|
|
2022-05-06 10:43:51 +02:00
|
|
|
void terminate();
|
|
|
|
|
void kill();
|
|
|
|
|
void interrupt();
|
2022-04-11 19:45:04 +02:00
|
|
|
void kickoffProcess();
|
2023-01-24 07:23:44 +01:00
|
|
|
void closeWriteChannel();
|
2022-03-29 18:01:08 +02:00
|
|
|
void close();
|
2022-06-03 14:28:30 +02:00
|
|
|
void stop();
|
2022-02-17 23:25:54 +01:00
|
|
|
|
2023-01-05 17:55:04 +01:00
|
|
|
QString readAllStandardOutput();
|
|
|
|
|
QString readAllStandardError();
|
|
|
|
|
|
|
|
|
|
QByteArray readAllRawStandardOutput();
|
|
|
|
|
QByteArray readAllRawStandardError();
|
2022-04-27 14:19:49 +02:00
|
|
|
|
2022-05-06 10:43:51 +02:00
|
|
|
qint64 write(const QString &input);
|
2022-04-27 14:19:49 +02:00
|
|
|
qint64 writeRaw(const QByteArray &input);
|
2022-02-17 23:25:54 +01:00
|
|
|
|
2022-05-06 10:43:51 +02:00
|
|
|
qint64 processId() const;
|
2022-04-11 19:45:04 +02:00
|
|
|
qint64 applicationMainThreadId() const;
|
|
|
|
|
|
2022-04-12 11:18:09 +02:00
|
|
|
QProcess::ProcessState state() const;
|
2022-10-06 17:04:05 +02:00
|
|
|
ProcessResultData resultData() const;
|
2022-04-08 17:24:59 +02:00
|
|
|
|
|
|
|
|
int exitCode() const;
|
|
|
|
|
QProcess::ExitStatus exitStatus() const;
|
2022-02-17 23:25:54 +01:00
|
|
|
|
2022-03-29 18:01:08 +02:00
|
|
|
QProcess::ProcessError error() const;
|
2022-04-08 17:24:59 +02:00
|
|
|
QString errorString() const;
|
2022-02-17 23:25:54 +01:00
|
|
|
|
2022-03-29 18:01:08 +02:00
|
|
|
bool waitForStarted(int msecs = 30000);
|
|
|
|
|
bool waitForReadyRead(int msecs = 30000);
|
|
|
|
|
bool waitForFinished(int msecs = 30000);
|
2022-02-17 23:25:54 +01:00
|
|
|
|
|
|
|
|
// ProcessSetupData related
|
|
|
|
|
|
2022-02-10 19:25:03 +01:00
|
|
|
void setProcessImpl(ProcessImpl processImpl);
|
|
|
|
|
|
2023-03-14 12:10:59 +01:00
|
|
|
void setPtyData(const std::optional<Pty::Data> &data);
|
|
|
|
|
std::optional<Pty::Data> ptyData() const;
|
2023-03-02 14:03:54 +01:00
|
|
|
|
2022-02-10 19:25:03 +01:00
|
|
|
void setTerminalMode(TerminalMode mode);
|
|
|
|
|
TerminalMode terminalMode() const;
|
2022-02-18 00:56:14 +01:00
|
|
|
bool usesTerminal() const { return terminalMode() != TerminalMode::Off; }
|
2022-02-10 19:25:03 +01:00
|
|
|
|
|
|
|
|
void setProcessMode(ProcessMode processMode);
|
|
|
|
|
ProcessMode processMode() const;
|
|
|
|
|
|
2022-05-09 15:02:23 +02:00
|
|
|
void setEnvironment(const Environment &env); // Main process
|
2021-05-05 16:05:53 +02:00
|
|
|
const Environment &environment() const;
|
|
|
|
|
|
2022-05-09 15:02:23 +02:00
|
|
|
void setControlEnvironment(const Environment &env); // Possible helper process (ssh on host etc)
|
|
|
|
|
const Environment &controlEnvironment() const;
|
2022-02-17 16:27:11 +01:00
|
|
|
|
2021-05-05 16:05:53 +02:00
|
|
|
void setCommand(const CommandLine &cmdLine);
|
|
|
|
|
const CommandLine &commandLine() const;
|
2019-05-28 18:59:45 +02:00
|
|
|
|
2021-06-03 10:39:15 +02:00
|
|
|
void setWorkingDirectory(const FilePath &dir);
|
2022-02-17 23:25:54 +01:00
|
|
|
FilePath workingDirectory() const;
|
|
|
|
|
|
|
|
|
|
void setWriteData(const QByteArray &writeData);
|
2021-05-14 15:21:54 +02:00
|
|
|
|
2022-03-14 17:02:11 +01:00
|
|
|
void setUseCtrlCStub(bool enabled); // release only
|
2021-05-05 16:05:53 +02:00
|
|
|
void setLowPriority();
|
|
|
|
|
void setDisableUnixTerminal();
|
2021-09-08 14:51:49 +02:00
|
|
|
void setRunAsRoot(bool on);
|
2022-02-01 14:51:23 +01:00
|
|
|
bool isRunAsRoot() const;
|
2022-01-21 16:15:17 +01:00
|
|
|
void setAbortOnMetaChars(bool abort);
|
|
|
|
|
|
2022-04-25 14:15:23 +02:00
|
|
|
QProcess::ProcessChannelMode processChannelMode() const;
|
2022-02-17 23:25:54 +01:00
|
|
|
void setProcessChannelMode(QProcess::ProcessChannelMode mode);
|
|
|
|
|
void setStandardInputFile(const QString &inputFile);
|
|
|
|
|
|
|
|
|
|
void setExtraData(const QString &key, const QVariant &value);
|
|
|
|
|
QVariant extraData(const QString &key) const;
|
|
|
|
|
|
|
|
|
|
void setExtraData(const QVariantHash &extraData);
|
|
|
|
|
QVariantHash extraData() const;
|
|
|
|
|
|
2022-06-03 14:28:30 +02:00
|
|
|
void setReaperTimeout(int msecs);
|
|
|
|
|
int reaperTimeout() const;
|
|
|
|
|
|
2022-02-17 23:25:54 +01:00
|
|
|
static void setRemoteProcessHooks(const DeviceProcessHooks &hooks);
|
|
|
|
|
|
|
|
|
|
// TODO: Some usages of this method assume that Starting phase is also a running state
|
|
|
|
|
// i.e. if isRunning() returns false, they assume NotRunning state, what may be an error.
|
|
|
|
|
bool isRunning() const; // Short for state() == QProcess::Running.
|
|
|
|
|
|
|
|
|
|
// Other enhancements.
|
|
|
|
|
// These (or some of them) may be potentially moved outside of the class.
|
|
|
|
|
// For some we may aggregate in another public utils class (or subclass of QtcProcess)?
|
|
|
|
|
|
|
|
|
|
// TODO: Unused currently? Should it serve as a compartment for contrary of remoteEnvironment?
|
|
|
|
|
static Environment systemEnvironmentForBinary(const FilePath &filePath);
|
|
|
|
|
|
2021-08-25 12:34:54 +02:00
|
|
|
static bool startDetached(const CommandLine &cmd, const FilePath &workingDirectory = {},
|
2021-08-12 12:33:28 +02:00
|
|
|
qint64 *pid = nullptr);
|
2022-01-24 19:57:52 +01:00
|
|
|
|
|
|
|
|
// Starts the command and waits for finish.
|
2022-03-23 16:39:47 +01:00
|
|
|
// User input processing is enabled when EventLoopMode::On was passed.
|
2022-03-02 04:12:25 +01:00
|
|
|
void runBlocking(EventLoopMode eventLoopMode = EventLoopMode::Off);
|
2021-06-22 04:24:13 +02:00
|
|
|
|
2021-05-06 11:15:28 +02:00
|
|
|
/* Timeout for hanging processes (triggers after no more output
|
|
|
|
|
* occurs on stderr/stdout). */
|
|
|
|
|
void setTimeoutS(int timeoutS);
|
2022-10-07 14:59:41 +02:00
|
|
|
int timeoutS() const;
|
2021-05-06 11:15:28 +02:00
|
|
|
|
2022-02-17 23:25:54 +01:00
|
|
|
// TODO: We should specify the purpose of the codec, e.g. setCodecForStandardChannel()
|
2021-05-06 11:15:28 +02:00
|
|
|
void setCodec(QTextCodec *c);
|
|
|
|
|
void setTimeOutMessageBoxEnabled(bool);
|
2022-03-02 04:12:25 +01:00
|
|
|
void setExitCodeInterpreter(const ExitCodeInterpreter &interpreter);
|
2021-05-06 11:15:28 +02:00
|
|
|
|
2022-10-07 12:05:37 +02:00
|
|
|
void setStdOutCallback(const TextChannelCallback &callback);
|
|
|
|
|
void setStdOutLineCallback(const TextChannelCallback &callback);
|
|
|
|
|
void setStdErrCallback(const TextChannelCallback &callback);
|
|
|
|
|
void setStdErrLineCallback(const TextChannelCallback &callback);
|
|
|
|
|
|
|
|
|
|
void setTextChannelMode(Channel channel, TextChannelMode mode);
|
|
|
|
|
TextChannelMode textChannelMode(Channel channel) const;
|
2021-05-06 11:15:28 +02:00
|
|
|
|
2022-07-05 18:07:05 +02:00
|
|
|
bool readDataFromProcess(QByteArray *stdOut, QByteArray *stdErr, int timeoutS = 30);
|
2021-05-06 13:07:36 +02:00
|
|
|
|
2022-03-02 04:12:25 +01:00
|
|
|
ProcessResult result() const;
|
2021-05-12 14:25:50 +02:00
|
|
|
|
|
|
|
|
QByteArray allRawOutput() const;
|
|
|
|
|
QString allOutput() const;
|
|
|
|
|
|
|
|
|
|
QByteArray rawStdOut() const;
|
|
|
|
|
|
2022-06-16 15:13:07 +02:00
|
|
|
QString stdOut() const; // possibly with CR
|
|
|
|
|
QString stdErr() const; // possibly with CR
|
|
|
|
|
|
2022-06-17 14:29:11 +02:00
|
|
|
QString cleanedStdOut() const; // with sequences of CR squashed and CR LF replaced by LF
|
|
|
|
|
QString cleanedStdErr() const; // with sequences of CR squashed and CR LF replaced by LF
|
2022-06-16 15:13:07 +02:00
|
|
|
|
|
|
|
|
const QStringList stdOutLines() const; // split, CR removed
|
|
|
|
|
const QStringList stdErrLines() const; // split, CR removed
|
|
|
|
|
|
2022-04-05 13:47:11 +02:00
|
|
|
QString exitMessage() const;
|
2021-05-12 14:25:50 +02:00
|
|
|
|
2021-09-09 23:03:39 +02:00
|
|
|
QString toStandaloneCommandLine() const;
|
|
|
|
|
|
2023-03-14 09:09:55 +01:00
|
|
|
void setCreateConsoleOnWindows(bool create);
|
|
|
|
|
bool createConsoleOnWindows() const;
|
|
|
|
|
|
2022-03-29 18:01:08 +02:00
|
|
|
signals:
|
2022-10-06 15:33:15 +02:00
|
|
|
void starting(); // On NotRunning -> Starting state transition
|
|
|
|
|
void started(); // On Starting -> Running state transition
|
|
|
|
|
void done(); // On Starting | Running -> NotRunning state transition
|
2022-03-29 18:01:08 +02:00
|
|
|
void readyReadStandardOutput();
|
|
|
|
|
void readyReadStandardError();
|
2022-10-07 12:05:37 +02:00
|
|
|
void textOnStandardOutput(const QString &text);
|
|
|
|
|
void textOnStandardError(const QString &text);
|
2022-03-29 18:01:08 +02:00
|
|
|
|
2021-05-06 13:07:36 +02:00
|
|
|
private:
|
2023-05-03 16:00:22 +02:00
|
|
|
friend QTCREATOR_UTILS_EXPORT QDebug operator<<(QDebug str, const Process &r);
|
2021-05-12 14:25:50 +02:00
|
|
|
|
2022-02-18 01:53:33 +01:00
|
|
|
friend class Internal::QtcProcessPrivate;
|
2021-05-06 13:07:36 +02:00
|
|
|
Internal::QtcProcessPrivate *d = nullptr;
|
|
|
|
|
};
|
|
|
|
|
|
2022-02-18 01:53:33 +01:00
|
|
|
class DeviceProcessHooks
|
2022-02-14 11:14:08 +01:00
|
|
|
{
|
|
|
|
|
public:
|
2022-02-21 12:49:14 +01:00
|
|
|
std::function<ProcessInterface *(const FilePath &)> processImplHook;
|
2022-02-18 01:53:33 +01:00
|
|
|
std::function<Environment(const FilePath &)> systemEnvironmentForBinary;
|
2022-02-14 11:14:08 +01:00
|
|
|
};
|
|
|
|
|
|
2023-05-03 16:00:22 +02:00
|
|
|
class QTCREATOR_UTILS_EXPORT ProcessTaskAdapter : public Tasking::TaskAdapter<Process>
|
2022-10-12 14:30:24 +02:00
|
|
|
{
|
|
|
|
|
public:
|
2023-05-03 14:06:15 +02:00
|
|
|
ProcessTaskAdapter();
|
2022-10-12 14:30:24 +02:00
|
|
|
void start() final;
|
|
|
|
|
};
|
|
|
|
|
|
2013-07-12 09:00:12 +02:00
|
|
|
} // namespace Utils
|
2022-10-12 14:30:24 +02:00
|
|
|
|
2023-05-03 14:06:15 +02:00
|
|
|
QTC_DECLARE_CUSTOM_TASK(ProcessTask, Utils::ProcessTaskAdapter);
|
2023-05-04 15:07:18 +02:00
|
|
|
|
|
|
|
|
#endif // UTILS_PROCESS_H
|