From a0f6e8dc04291138ec2305fe7c02a0a460f57fac Mon Sep 17 00:00:00 2001 From: Jarek Kobus Date: Wed, 3 May 2023 17:05:35 +0200 Subject: Utils: Rename qtcprocess.{cpp,h} -> process.{cpp,h} Follows QtcProcess -> Process rename. Change-Id: I97235a9a40cb7fd52944515b7ab878d96528f919 Reviewed-by: hjk Reviewed-by: Qt CI Bot --- src/libs/extensionsystem/pluginmanager.cpp | 2 +- src/libs/qmljs/qmljsplugindumper.cpp | 2 +- src/libs/utils/CMakeLists.txt | 2 +- src/libs/utils/archive.cpp | 2 +- src/libs/utils/buildablehelperlibrary.cpp | 2 +- src/libs/utils/clangutils.cpp | 2 +- src/libs/utils/devicefileaccess.cpp | 2 +- src/libs/utils/deviceshell.cpp | 2 +- src/libs/utils/filestreamer.cpp | 2 +- src/libs/utils/pathchooser.cpp | 2 +- src/libs/utils/process.cpp | 2163 ++++++++++++++++++++ src/libs/utils/process.h | 219 ++ src/libs/utils/processinfo.cpp | 2 +- src/libs/utils/qtcprocess.cpp | 2163 -------------------- src/libs/utils/qtcprocess.h | 219 -- src/libs/utils/terminalhooks.cpp | 2 +- src/libs/utils/utils.qbs | 4 +- src/plugins/android/androidavdmanager.cpp | 2 +- src/plugins/android/androidbuildapkstep.cpp | 2 +- src/plugins/android/androidconfigurations.cpp | 2 +- .../android/androidcreatekeystorecertificate.cpp | 2 +- src/plugins/android/androiddebugsupport.cpp | 2 +- src/plugins/android/androiddeployqtstep.cpp | 2 +- src/plugins/android/androiddevice.cpp | 2 +- src/plugins/android/androidmanager.cpp | 2 +- .../android/androidpackageinstallationstep.cpp | 2 +- src/plugins/android/androidqmlpreviewworker.cpp | 2 +- src/plugins/android/androidrunconfiguration.cpp | 2 +- src/plugins/android/androidrunnerworker.cpp | 2 +- src/plugins/android/androidsdkmanager.cpp | 2 +- src/plugins/android/androidsettingswidget.cpp | 2 +- src/plugins/android/androidsignaloperation.cpp | 2 +- .../autotest/boost/boosttestoutputreader.cpp | 2 +- src/plugins/autotest/gtest/gtestoutputreader.cpp | 2 +- src/plugins/autotest/testoutputreader.cpp | 2 +- src/plugins/autotest/testrunner.cpp | 2 +- .../autotoolsprojectmanager/makefileparser.cpp | 2 +- src/plugins/baremetal/baremetaldebugsupport.cpp | 2 +- .../debugservers/gdb/jlinkgdbserverprovider.cpp | 2 +- .../debugservers/gdb/openocdgdbserverprovider.cpp | 2 +- .../debugservers/uvsc/uvscserverprovider.h | 2 +- src/plugins/baremetal/iarewtoolchain.cpp | 2 +- src/plugins/baremetal/keiltoolchain.cpp | 2 +- src/plugins/baremetal/sdcctoolchain.cpp | 2 +- src/plugins/beautifier/abstractsettings.cpp | 2 +- .../artisticstyle/artisticstylesettings.cpp | 2 +- src/plugins/beautifier/beautifierplugin.cpp | 2 +- .../beautifier/uncrustify/uncrustifysettings.cpp | 2 +- .../boot2qt/device-detection/qdbwatcher.cpp | 2 +- src/plugins/boot2qt/qdbdevice.cpp | 2 +- src/plugins/boot2qt/qdbdevicedebugsupport.cpp | 2 +- src/plugins/boot2qt/qdbmakedefaultappstep.cpp | 2 +- src/plugins/boot2qt/qdbplugin.cpp | 4 +- src/plugins/boot2qt/qdbstopapplicationstep.cpp | 2 +- src/plugins/clangtools/clangtoolruncontrol.cpp | 2 +- src/plugins/clangtools/clangtoolrunner.cpp | 2 +- src/plugins/clangtools/clangtoolsutils.cpp | 2 +- src/plugins/clangtools/executableinfo.cpp | 2 +- src/plugins/clearcase/clearcaseplugin.cpp | 2 +- src/plugins/clearcase/clearcasesync.cpp | 2 +- .../cmakeprojectmanager/cmakebuildsystem.cpp | 2 +- .../cmakeprojectmanager/cmakeformattersettings.cpp | 2 +- src/plugins/cmakeprojectmanager/cmakeprocess.cpp | 2 +- .../cmakeprojectmanager/cmakeprojectimporter.cpp | 2 +- src/plugins/cmakeprojectmanager/cmaketool.cpp | 2 +- .../cmakeprojectmanager/fileapidataextractor.cpp | 2 +- .../coreplugin/dialogs/externaltoolconfig.cpp | 2 +- src/plugins/coreplugin/externaltool.cpp | 2 +- src/plugins/coreplugin/fileutils.cpp | 2 +- src/plugins/coreplugin/locator/executefilter.cpp | 2 +- .../coreplugin/locator/spotlightlocatorfilter.cpp | 2 +- src/plugins/coreplugin/patchtool.cpp | 2 +- src/plugins/coreplugin/plugininstallwizard.cpp | 2 +- .../coreplugin/progressmanager/processprogress.cpp | 2 +- src/plugins/cppcheck/cppcheckrunner.h | 2 +- src/plugins/cppeditor/cppcodemodelsettings.cpp | 2 +- src/plugins/cppeditor/cppmodelmanager.cpp | 2 +- src/plugins/debugger/cdb/cdbengine.cpp | 2 +- src/plugins/debugger/cdb/cdbengine.h | 2 +- src/plugins/debugger/dap/dapengine.cpp | 2 +- src/plugins/debugger/dap/dapengine.h | 2 +- src/plugins/debugger/debuggerengine.cpp | 2 +- src/plugins/debugger/debuggeritem.cpp | 2 +- src/plugins/debugger/debuggeritemmanager.cpp | 2 +- src/plugins/debugger/debuggerruncontrol.cpp | 2 +- .../debugger/debuggersourcepathmappingwidget.cpp | 2 +- src/plugins/debugger/gdb/gdbengine.cpp | 2 +- src/plugins/debugger/gdb/gdbengine.h | 2 +- src/plugins/debugger/lldb/lldbengine.cpp | 2 +- src/plugins/debugger/lldb/lldbengine.h | 2 +- src/plugins/debugger/moduleshandler.cpp | 2 +- src/plugins/debugger/pdb/pdbengine.cpp | 2 +- src/plugins/debugger/pdb/pdbengine.h | 2 +- src/plugins/debugger/qml/qmlengine.cpp | 2 +- src/plugins/debugger/terminal.cpp | 2 +- src/plugins/docker/dockerapi.cpp | 2 +- src/plugins/docker/dockerdevice.cpp | 2 +- src/plugins/fakevim/fakevimplugin.cpp | 2 +- src/plugins/fossil/fossilclient.cpp | 2 +- .../genericprojectmanager/genericproject.cpp | 2 +- src/plugins/git/branchmodel.cpp | 2 +- src/plugins/git/changeselectiondialog.cpp | 2 +- src/plugins/git/gerrit/gerritmodel.cpp | 2 +- src/plugins/git/gerrit/gerritplugin.cpp | 2 +- src/plugins/git/gitclient.cpp | 2 +- src/plugins/git/gitclient.h | 2 +- src/plugins/git/gitgrep.cpp | 2 +- src/plugins/git/mergetool.h | 2 +- src/plugins/gitlab/gitlabclonedialog.cpp | 2 +- src/plugins/gitlab/queryrunner.h | 2 +- src/plugins/haskell/haskellmanager.cpp | 2 +- src/plugins/incredibuild/cmakecommandbuilder.cpp | 2 +- src/plugins/ios/iosbuildstep.cpp | 2 +- src/plugins/ios/iosconfigurations.cpp | 2 +- src/plugins/ios/iosdsymbuildstep.cpp | 11 +- src/plugins/ios/iosprobe.cpp | 2 +- src/plugins/ios/iosrunconfiguration.cpp | 4 +- src/plugins/ios/iosrunner.cpp | 2 +- src/plugins/ios/iossimulator.cpp | 2 +- src/plugins/ios/iostoolhandler.cpp | 2 +- src/plugins/ios/simulatorcontrol.cpp | 2 +- src/plugins/languageclient/client.cpp | 2 +- .../languageclient/languageclientinterface.h | 2 +- src/plugins/mcusupport/mcuqmlprojectnode.h | 2 +- .../mcusupport/mcusupportversiondetection.cpp | 2 +- src/plugins/mercurial/mercurialclient.cpp | 2 +- .../mesonbuildconfiguration.cpp | 2 +- src/plugins/mesonprojectmanager/mesonprocess.cpp | 2 +- src/plugins/mesonprojectmanager/mesonwrapper.h | 2 +- src/plugins/mesonprojectmanager/toolwrapper.cpp | 2 +- src/plugins/nim/project/nimblebuildsystem.cpp | 2 +- src/plugins/nim/project/nimcompilerbuildstep.cpp | 2 +- src/plugins/nim/project/nimtoolchain.cpp | 2 +- src/plugins/nim/suggest/server.h | 2 +- src/plugins/perforce/perforcechecker.h | 2 +- src/plugins/perforce/perforceplugin.cpp | 2 +- src/plugins/perfprofiler/perfconfigwidget.cpp | 2 +- .../perfprofiler/perfprofilerruncontrol.cpp | 2 +- src/plugins/perfprofiler/perfsettings.cpp | 2 +- src/plugins/perfprofiler/perftracepointdialog.cpp | 4 +- .../projectexplorer/abstractprocessstep.cpp | 2 +- .../customwizard/customwizardscriptgenerator.cpp | 2 +- .../devicesupport/desktopdevice.cpp | 2 +- .../devicesupport/devicemanager.cpp | 2 +- .../devicesupport/deviceusedportsgatherer.cpp | 2 +- .../devicesupport/sshparameters.cpp | 2 +- src/plugins/projectexplorer/extracompiler.cpp | 2 +- src/plugins/projectexplorer/gcctoolchain.cpp | 2 +- src/plugins/projectexplorer/makestep.cpp | 2 +- src/plugins/projectexplorer/msvctoolchain.cpp | 2 +- src/plugins/projectexplorer/processparameters.cpp | 2 +- src/plugins/projectexplorer/projectmodels.cpp | 2 +- .../projectexplorer/runconfigurationaspects.cpp | 2 +- src/plugins/projectexplorer/runcontrol.cpp | 2 +- src/plugins/projectexplorer/targetsetuppage.cpp | 7 +- src/plugins/projectexplorer/taskfile.cpp | 2 +- .../projectexplorer/toolchainconfigwidget.cpp | 2 +- src/plugins/projectexplorer/userfileaccessor.cpp | 2 +- src/plugins/python/pipsupport.cpp | 2 +- src/plugins/python/pipsupport.h | 2 +- src/plugins/python/pyside.cpp | 3 +- src/plugins/python/pysideuicextracompiler.cpp | 2 +- src/plugins/python/pythonlanguageclient.cpp | 2 +- src/plugins/python/pythonsettings.cpp | 2 +- src/plugins/python/pythonutils.cpp | 2 +- .../qbsprojectmanager/qbsbuildconfiguration.cpp | 2 +- src/plugins/qbsprojectmanager/qbsbuildstep.cpp | 2 +- .../qbsprojectmanager/qbsprofilemanager.cpp | 2 +- src/plugins/qbsprojectmanager/qbssession.cpp | 2 +- src/plugins/qbsprojectmanager/qbssettings.cpp | 2 +- .../librarydetailscontroller.cpp | 2 +- src/plugins/qmakeprojectmanager/makefileparse.cpp | 2 +- .../qmakebuildconfiguration.cpp | 2 +- src/plugins/qmakeprojectmanager/qmakemakestep.cpp | 2 +- .../qmakeprojectmanager/qmakeparsernodes.cpp | 2 +- src/plugins/qmakeprojectmanager/qmakeproject.cpp | 2 +- .../qmakeprojectmanager/qmakeprojectimporter.cpp | 2 +- src/plugins/qmakeprojectmanager/qmakestep.cpp | 2 +- .../componentcore/modelnodeoperations.cpp | 2 +- .../designercore/instances/nodeinstanceview.cpp | 2 +- src/plugins/qmldesigner/generateresource.cpp | 2 +- src/plugins/qmlpreview/qmlpreviewruncontrol.cpp | 2 +- src/plugins/qmlprofiler/qmlprofilerruncontrol.cpp | 2 +- src/plugins/qmlprojectmanager/qmlproject.cpp | 2 +- src/plugins/qmlprojectmanager/qmlprojectplugin.cpp | 2 +- .../qmlprojectrunconfiguration.cpp | 2 +- src/plugins/qnx/qnxanalyzesupport.cpp | 3 +- src/plugins/qnx/qnxdebugsupport.cpp | 2 +- src/plugins/qnx/qnxdeployqtlibrariesdialog.cpp | 2 +- src/plugins/qnx/qnxdevice.cpp | 2 +- src/plugins/qnx/qnxdevicetester.cpp | 3 +- src/plugins/qnx/qnxutils.cpp | 2 +- src/plugins/qnx/slog2inforunner.cpp | 2 +- src/plugins/qtsupport/baseqtversion.cpp | 2 +- src/plugins/qtsupport/externaleditors.cpp | 2 +- src/plugins/qtsupport/qtsupportplugin.cpp | 2 +- src/plugins/qtsupport/qtversionmanager.cpp | 2 +- src/plugins/qtsupport/uicgenerator.cpp | 9 +- .../remotelinux/customcommanddeploystep.cpp | 2 +- src/plugins/remotelinux/filesystemaccess_test.cpp | 2 +- .../remotelinux/genericdirectuploadstep.cpp | 2 +- src/plugins/remotelinux/linuxdevice.cpp | 2 +- src/plugins/remotelinux/linuxdevicetester.cpp | 2 +- src/plugins/remotelinux/makeinstallstep.cpp | 2 +- .../remotelinux/publickeydeploymentdialog.cpp | 2 +- .../remotelinux/remotelinuxsignaloperation.cpp | 2 +- src/plugins/remotelinux/rsyncdeploystep.cpp | 2 +- src/plugins/remotelinux/sshkeycreationdialog.cpp | 2 +- src/plugins/remotelinux/tarpackagedeploystep.cpp | 2 +- .../silversearcher/findinfilessilversearcher.cpp | 2 +- src/plugins/squish/objectsmapdocument.cpp | 2 +- src/plugins/squish/squishprocessbase.h | 2 +- src/plugins/squish/squishtools.h | 2 +- src/plugins/subversion/subversionclient.cpp | 3 +- src/plugins/terminal/shellintegration.h | 2 +- src/plugins/terminal/terminalwidget.h | 2 +- src/plugins/texteditor/formattexteditor.cpp | 2 +- src/plugins/updateinfo/updateinfoplugin.cpp | 2 +- src/plugins/valgrind/callgrindengine.cpp | 2 +- src/plugins/valgrind/callgrindengine.h | 2 +- src/plugins/valgrind/callgrindtool.cpp | 2 +- src/plugins/valgrind/memchecktool.cpp | 2 +- src/plugins/valgrind/valgrindrunner.cpp | 2 +- src/plugins/vcsbase/vcsbaseclient.cpp | 2 +- .../vcsbase/vcsbasediffeditorcontroller.cpp | 2 +- src/plugins/vcsbase/vcsbaseplugin.cpp | 2 +- src/plugins/vcsbase/vcsbasesubmiteditor.cpp | 2 +- src/plugins/vcsbase/vcscommand.cpp | 2 +- src/plugins/vcsbase/vcsoutputwindow.cpp | 2 +- src/plugins/webassembly/webassemblyemsdk.cpp | 2 +- .../webassemblyrunconfigurationaspects.cpp | 2 +- tests/auto/utils/commandline/tst_commandline.cpp | 2 +- tests/auto/utils/deviceshell/tst_deviceshell.cpp | 2 +- .../auto/utils/qtcprocess/processtestapp/main.cpp | 2 +- .../qtcprocess/processtestapp/processtestapp.cpp | 2 +- tests/auto/utils/qtcprocess/tst_qtcprocess.cpp | 2 +- tests/manual/deviceshell/tst_deviceshell.cpp | 2 +- 237 files changed, 2630 insertions(+), 2633 deletions(-) create mode 100644 src/libs/utils/process.cpp create mode 100644 src/libs/utils/process.h delete mode 100644 src/libs/utils/qtcprocess.cpp delete mode 100644 src/libs/utils/qtcprocess.h diff --git a/src/libs/extensionsystem/pluginmanager.cpp b/src/libs/extensionsystem/pluginmanager.cpp index c22cdfdca0..3ee9951055 100644 --- a/src/libs/extensionsystem/pluginmanager.cpp +++ b/src/libs/extensionsystem/pluginmanager.cpp @@ -35,8 +35,8 @@ #include #include #include +#include #include -#include #include #include diff --git a/src/libs/qmljs/qmljsplugindumper.cpp b/src/libs/qmljs/qmljsplugindumper.cpp index b566905735..761df90ddc 100644 --- a/src/libs/qmljs/qmljsplugindumper.cpp +++ b/src/libs/qmljs/qmljsplugindumper.cpp @@ -13,7 +13,7 @@ #include #include #include -#include +#include #include #include diff --git a/src/libs/utils/CMakeLists.txt b/src/libs/utils/CMakeLists.txt index f26c08c7b5..defbbf2794 100644 --- a/src/libs/utils/CMakeLists.txt +++ b/src/libs/utils/CMakeLists.txt @@ -127,6 +127,7 @@ add_qtc_library(Utils port.cpp port.h portlist.cpp portlist.h predicates.h + process.cpp process.h processenums.h processhandle.cpp processhandle.h processinfo.cpp processinfo.h @@ -139,7 +140,6 @@ add_qtc_library(Utils qrcparser.cpp qrcparser.h qtcassert.cpp qtcassert.h qtcolorbutton.cpp qtcolorbutton.h - qtcprocess.cpp qtcprocess.h qtcsettings.cpp qtcsettings.h ranges.h reloadpromptutils.cpp reloadpromptutils.h diff --git a/src/libs/utils/archive.cpp b/src/libs/utils/archive.cpp index db541293e3..5e62835a20 100644 --- a/src/libs/utils/archive.cpp +++ b/src/libs/utils/archive.cpp @@ -5,8 +5,8 @@ #include "algorithm.h" #include "mimeutils.h" +#include "process.h" #include "qtcassert.h" -#include "qtcprocess.h" #include "utilstr.h" #include diff --git a/src/libs/utils/buildablehelperlibrary.cpp b/src/libs/utils/buildablehelperlibrary.cpp index f4cb50b454..cafd5b0452 100644 --- a/src/libs/utils/buildablehelperlibrary.cpp +++ b/src/libs/utils/buildablehelperlibrary.cpp @@ -4,7 +4,7 @@ #include "buildablehelperlibrary.h" #include "environment.h" #include "hostosinfo.h" -#include "qtcprocess.h" +#include "process.h" #include #include diff --git a/src/libs/utils/clangutils.cpp b/src/libs/utils/clangutils.cpp index 4c8c7d801d..6cf265820e 100644 --- a/src/libs/utils/clangutils.cpp +++ b/src/libs/utils/clangutils.cpp @@ -4,7 +4,7 @@ #include "clangutils.h" #include "filepath.h" -#include "qtcprocess.h" +#include "process.h" #include "utilstr.h" #include diff --git a/src/libs/utils/devicefileaccess.cpp b/src/libs/utils/devicefileaccess.cpp index 6b07fbdeb4..bda098e0f6 100644 --- a/src/libs/utils/devicefileaccess.cpp +++ b/src/libs/utils/devicefileaccess.cpp @@ -13,7 +13,7 @@ #include "utilstr.h" #ifndef UTILS_STATIC_LIBRARY -#include "qtcprocess.h" +#include "process.h" #endif #include diff --git a/src/libs/utils/deviceshell.cpp b/src/libs/utils/deviceshell.cpp index 0641c10c38..627fee3d67 100644 --- a/src/libs/utils/deviceshell.cpp +++ b/src/libs/utils/deviceshell.cpp @@ -3,9 +3,9 @@ #include "deviceshell.h" +#include "process.h" #include "processinterface.h" #include "qtcassert.h" -#include "qtcprocess.h" #include #include diff --git a/src/libs/utils/filestreamer.cpp b/src/libs/utils/filestreamer.cpp index e4dea9887d..a42e632000 100644 --- a/src/libs/utils/filestreamer.cpp +++ b/src/libs/utils/filestreamer.cpp @@ -5,7 +5,7 @@ #include "async.h" #include "barrier.h" -#include "qtcprocess.h" +#include "process.h" #include #include diff --git a/src/libs/utils/pathchooser.cpp b/src/libs/utils/pathchooser.cpp index 0c43e8f527..1fe1e96256 100644 --- a/src/libs/utils/pathchooser.cpp +++ b/src/libs/utils/pathchooser.cpp @@ -10,8 +10,8 @@ #include "hostosinfo.h" #include "macroexpander.h" #include "optionpushbutton.h" +#include "process.h" #include "qtcassert.h" -#include "qtcprocess.h" #include "utilstr.h" #include diff --git a/src/libs/utils/process.cpp b/src/libs/utils/process.cpp new file mode 100644 index 0000000000..1b11bd8645 --- /dev/null +++ b/src/libs/utils/process.cpp @@ -0,0 +1,2163 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 + +#include "process.h" + +#include "algorithm.h" +#include "environment.h" +#include "guard.h" +#include "hostosinfo.h" +#include "launcherinterface.h" +#include "launchersocket.h" +#include "processreaper.h" +#include "processutils.h" +#include "stringutils.h" +#include "terminalhooks.h" +#include "threadutils.h" +#include "utilstr.h" + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef QT_GUI_LIB +// qmlpuppet does not use that. +#include +#include +#endif + +#include +#include +#include +#include +#include +#include +#include + +using namespace Utils::Internal; + +namespace Utils { +namespace Internal { + +const char QTC_PROCESS_BLOCKING_TYPE[] = "__BLOCKING_TYPE__"; +const char QTC_PROCESS_NUMBER[] = "__NUMBER__"; +const char QTC_PROCESS_STARTTIME[] = "__STARTTIME__"; + +class MeasureAndRun +{ +public: + MeasureAndRun(const char *functionName) + : m_functionName(functionName) + , m_measureProcess(qtcEnvironmentVariableIsSet("QTC_MEASURE_PROCESS")) + {} + template + std::invoke_result_t measureAndRun(Function &&function, Args&&... args) + { + if (!m_measureProcess) + return std::invoke(std::forward(function), std::forward(args)...); + QElapsedTimer timer; + timer.start(); + auto cleanup = qScopeGuard([this, &timer] { + const qint64 currentNsecs = timer.nsecsElapsed(); + const bool mainThread = isMainThread(); + const int hitThisAll = m_hitThisAll.fetch_add(1) + 1; + const int hitAllAll = m_hitAllAll.fetch_add(1) + 1; + const int hitThisMain = mainThread + ? m_hitThisMain.fetch_add(1) + 1 + : m_hitThisMain.load(); + const int hitAllMain = mainThread + ? m_hitAllMain.fetch_add(1) + 1 + : m_hitAllMain.load(); + const qint64 totalThisAll = toMs(m_totalThisAll.fetch_add(currentNsecs) + currentNsecs); + const qint64 totalAllAll = toMs(m_totalAllAll.fetch_add(currentNsecs) + currentNsecs); + const qint64 totalThisMain = toMs(mainThread + ? m_totalThisMain.fetch_add(currentNsecs) + currentNsecs + : m_totalThisMain.load()); + const qint64 totalAllMain = toMs(mainThread + ? m_totalAllMain.fetch_add(currentNsecs) + currentNsecs + : m_totalAllMain.load()); + printMeasurement(QLatin1String(m_functionName), hitThisAll, toMs(currentNsecs), + totalThisAll, hitAllAll, totalAllAll, mainThread, + hitThisMain, totalThisMain, hitAllMain, totalAllMain); + }); + return std::invoke(std::forward(function), std::forward(args)...); + } +private: + static void printHeader() + { + // [function/thread]: function:(T)his|(A)ll, thread:(M)ain|(A)ll + qDebug() << "+----------------+-------+---------+----------+-------+----------+---------+-------+----------+-------+----------+"; + qDebug() << "| [Function/Thread] = [(T|A)/(M|A)], where: (T)his function, (A)ll functions / threads, (M)ain thread |"; + qDebug() << "+----------------+-------+---------+----------+-------+----------+---------+-------+----------+-------+----------+"; + qDebug() << "| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 |"; + qDebug() << "| | [T/A] | [T/A] | [T/A] | [A/A] | [A/A] | | [T/M] | [T/M] | [A/M] | [A/M] |"; + qDebug() << "| Function | Hit | Current | Total | Hit | Total | Current | Hit | Total | Hit | Total |"; + qDebug() << "| Name | Count | Measu- | Measu- | Count | Measu- | is Main | Count | Measu- | Count | Measu- |"; + qDebug() << "| | | rement | rement | | rement | Thread | | rement | | rement |"; + qDebug() << "+----------------+-------+---------+----------+-------+----------+---------+-------+----------+-------+----------+"; + } + static void printMeasurement(const QString &functionName, int hitThisAll, int currentNsecs, + int totalThisAll, int hitAllAll, int totalAllAll, bool isMainThread, + int hitThisMain, int totalThisMain, int hitAllMain, int totalAllMain) + { + static const int repeatHeaderLineCount = 25; + if (s_lineCounter.fetch_add(1) % repeatHeaderLineCount == 0) + printHeader(); + + const QString &functionNameField = QString("%1").arg(functionName, 14); + const QString &hitThisAllField = formatField(hitThisAll, 5); + const QString ¤tNsecsField = formatField(currentNsecs, 7, " ms"); + const QString &totalThisAllField = formatField(totalThisAll, 8, " ms"); + const QString &hitAllAllField = formatField(hitAllAll, 5); + const QString &totalAllAllField = formatField(totalAllAll, 8, " ms"); + const QString &mainThreadField = isMainThread ? QString("%1").arg("yes", 7) + : QString("%1").arg("no", 7); + const QString &hitThisMainField = formatField(hitThisMain, 5); + const QString &totalThisMainField = formatField(totalThisMain, 8, " ms"); + const QString &hitAllMainField = formatField(hitAllMain, 5); + const QString &totalAllMainField = formatField(totalAllMain, 8, " ms"); + + const QString &totalString = QString("| %1 | %2 | %3 | %4 | %5 | %6 | %7 | %8 | %9 | %10 | %11 |") + .arg(functionNameField, hitThisAllField, currentNsecsField, + totalThisAllField, hitAllAllField, totalAllAllField, mainThreadField, + hitThisMainField, totalThisMainField, hitAllMainField, totalAllMainField); + qDebug("%s", qPrintable(totalString)); + } + static QString formatField(int number, int fieldWidth, const QString &suffix = {}) + { + return QString("%1%2").arg(number, fieldWidth - suffix.count()).arg(suffix); + } + + static int toMs(quint64 nsesc) // nanoseconds to miliseconds + { + static const int halfMillion = 500000; + static const int million = 2 * halfMillion; + return int((nsesc + halfMillion) / million); + } + + const char * const m_functionName; + const bool m_measureProcess; + std::atomic_int m_hitThisAll = 0; + std::atomic_int m_hitThisMain = 0; + std::atomic_int64_t m_totalThisAll = 0; + std::atomic_int64_t m_totalThisMain = 0; + static std::atomic_int m_hitAllAll; + static std::atomic_int m_hitAllMain; + static std::atomic_int64_t m_totalAllAll; + static std::atomic_int64_t m_totalAllMain; + static std::atomic_int s_lineCounter; +}; + +std::atomic_int MeasureAndRun::m_hitAllAll = 0; +std::atomic_int MeasureAndRun::m_hitAllMain = 0; +std::atomic_int64_t MeasureAndRun::m_totalAllAll = 0; +std::atomic_int64_t MeasureAndRun::m_totalAllMain = 0; +std::atomic_int MeasureAndRun::s_lineCounter = 0; + +static MeasureAndRun s_start = MeasureAndRun("start"); +static MeasureAndRun s_waitForStarted = MeasureAndRun("waitForStarted"); + +enum { debug = 0 }; +enum { syncDebug = 0 }; + +enum { defaultMaxHangTimerCount = 10 }; + +static Q_LOGGING_CATEGORY(processLog, "qtc.utils.qtcprocess", QtWarningMsg) +static Q_LOGGING_CATEGORY(processStdoutLog, "qtc.utils.qtcprocess.stdout", QtWarningMsg) +static Q_LOGGING_CATEGORY(processStderrLog, "qtc.utils.qtcprocess.stderr", QtWarningMsg) + +static DeviceProcessHooks s_deviceHooks; + +// Data for one channel buffer (stderr/stdout) +class ChannelBuffer +{ +public: + void clearForRun(); + + void handleRest(); + void append(const QByteArray &text); + + QByteArray readAllData() { return std::exchange(rawData, {}); } + + QByteArray rawData; + QString incompleteLineBuffer; // lines not yet signaled + QTextCodec *codec = nullptr; // Not owner + std::unique_ptr codecState; + std::function outputCallback; + TextChannelMode m_textChannelMode = TextChannelMode::Off; + + bool emitSingleLines = true; + bool keepRawData = true; +}; + +class DefaultImpl : public ProcessInterface +{ +private: + virtual void start() final; + virtual void doDefaultStart(const QString &program, const QStringList &arguments) = 0; + bool dissolveCommand(QString *program, QStringList *arguments); + bool ensureProgramExists(const QString &program); +}; + +void DefaultImpl::start() +{ + QString program; + QStringList arguments; + if (!dissolveCommand(&program, &arguments)) + return; + if (!ensureProgramExists(program)) + return; + s_start.measureAndRun(&DefaultImpl::doDefaultStart, this, program, arguments); +} + +bool DefaultImpl::dissolveCommand(QString *program, QStringList *arguments) +{ + const CommandLine &commandLine = m_setup.m_commandLine; + QString commandString; + ProcessArgs processArgs; + const bool success = ProcessArgs::prepareCommand(commandLine, &commandString, &processArgs, + &m_setup.m_environment, + &m_setup.m_workingDirectory); + + if (commandLine.executable().osType() == OsTypeWindows) { + QString args; + if (m_setup.m_useCtrlCStub) { + if (m_setup.m_lowPriority) + ProcessArgs::addArg(&args, "-nice"); + ProcessArgs::addArg(&args, QDir::toNativeSeparators(commandString)); + commandString = QCoreApplication::applicationDirPath() + + QLatin1String("/qtcreator_ctrlc_stub.exe"); + } else if (m_setup.m_lowPriority) { + m_setup.m_belowNormalPriority = true; + } + ProcessArgs::addArgs(&args, processArgs.toWindowsArgs()); + m_setup.m_nativeArguments = args; + // Note: Arguments set with setNativeArgs will be appended to the ones + // passed with start() below. + *arguments = {}; + } else { + if (!success) { + const ProcessResultData result = {0, + QProcess::NormalExit, + QProcess::FailedToStart, + Tr::tr("Error in command line.")}; + emit done(result); + return false; + } + *arguments = processArgs.toUnixArgs(); + } + *program = commandString; + return true; +} + +static FilePath resolve(const FilePath &workingDir, const FilePath &filePath) +{ + if (filePath.isAbsolutePath()) + return filePath; + + const FilePath fromWorkingDir = workingDir.resolvePath(filePath); + if (fromWorkingDir.exists() && fromWorkingDir.isExecutableFile()) + return fromWorkingDir; + return filePath.searchInPath(); +} + +bool DefaultImpl::ensureProgramExists(const QString &program) +{ + const FilePath programFilePath = resolve(m_setup.m_workingDirectory, + FilePath::fromString(program)); + if (programFilePath.exists() && programFilePath.isExecutableFile()) + return true; + + const QString errorString + = Tr::tr("The program \"%1\" does not exist or is not executable.").arg(program); + const ProcessResultData result = { 0, QProcess::NormalExit, QProcess::FailedToStart, + errorString }; + emit done(result); + return false; +} + +class QProcessBlockingImpl : public ProcessBlockingInterface +{ +public: + QProcessBlockingImpl(QProcess *process) : m_process(process) {} + +private: + bool waitForSignal(ProcessSignalType signalType, int msecs) final + { + switch (signalType) { + case ProcessSignalType::Started: + return m_process->waitForStarted(msecs); + case ProcessSignalType::ReadyRead: + return m_process->waitForReadyRead(msecs); + case ProcessSignalType::Done: + return m_process->waitForFinished(msecs); + } + return false; + } + + QProcess *m_process = nullptr; +}; + +class PtyProcessImpl final : public DefaultImpl +{ +public: + ~PtyProcessImpl() { QTC_CHECK(m_setup.m_ptyData); m_setup.m_ptyData->setResizeHandler({}); } + + qint64 write(const QByteArray &data) final + { + if (m_ptyProcess) + return m_ptyProcess->write(data); + return -1; + } + + void sendControlSignal(ControlSignal controlSignal) final + { + if (!m_ptyProcess) + return; + + switch (controlSignal) { + case ControlSignal::Terminate: + m_ptyProcess.reset(); + break; + case ControlSignal::Kill: + m_ptyProcess->kill(); + break; + default: + QTC_CHECK(false); + } + } + + void doDefaultStart(const QString &program, const QStringList &arguments) final + { + QTC_CHECK(m_setup.m_ptyData); + m_setup.m_ptyData->setResizeHandler([this](const QSize &size) { + if (m_ptyProcess) + m_ptyProcess->resize(size.width(), size.height()); + }); + m_ptyProcess.reset(PtyQt::createPtyProcess(IPtyProcess::AutoPty)); + if (!m_ptyProcess) { + const ProcessResultData result = {-1, + QProcess::CrashExit, + QProcess::FailedToStart, + "Failed to create pty process"}; + emit done(result); + return; + } + + QProcessEnvironment penv = m_setup.m_environment.toProcessEnvironment(); + if (penv.isEmpty()) + penv = Environment::systemEnvironment().toProcessEnvironment(); + const QStringList senv = penv.toStringList(); + + bool startResult + = m_ptyProcess->startProcess(program, + HostOsInfo::isWindowsHost() + ? QStringList{m_setup.m_nativeArguments} << arguments + : arguments, + m_setup.m_workingDirectory.nativePath(), + senv, + m_setup.m_ptyData->size().width(), + m_setup.m_ptyData->size().height()); + + if (!startResult) { + const ProcessResultData result = {-1, + QProcess::CrashExit, + QProcess::FailedToStart, + "Failed to start pty process: " + + m_ptyProcess->lastError()}; + emit done(result); + return; + } + + if (!m_ptyProcess->lastError().isEmpty()) { + const ProcessResultData result + = {-1, QProcess::CrashExit, QProcess::FailedToStart, m_ptyProcess->lastError()}; + emit done(result); + return; + } + + connect(m_ptyProcess->notifier(), &QIODevice::readyRead, this, [this] { + emit readyRead(m_ptyProcess->readAll(), {}); + }); + + connect(m_ptyProcess->notifier(), &QIODevice::aboutToClose, this, [this] { + if (m_ptyProcess) { + const ProcessResultData result + = {m_ptyProcess->exitCode(), QProcess::NormalExit, QProcess::UnknownError, {}}; + emit done(result); + return; + } + + const ProcessResultData result = {0, QProcess::NormalExit, QProcess::UnknownError, {}}; + emit done(result); + }); + + emit started(m_ptyProcess->pid()); + } + +private: + std::unique_ptr m_ptyProcess; +}; + +class QProcessImpl final : public DefaultImpl +{ +public: + QProcessImpl() + : m_process(new ProcessHelper(this)) + , m_blockingImpl(new QProcessBlockingImpl(m_process)) + { + connect(m_process, &QProcess::started, this, &QProcessImpl::handleStarted); + connect(m_process, &QProcess::finished, this, &QProcessImpl::handleFinished); + connect(m_process, &QProcess::errorOccurred, this, &QProcessImpl::handleError); + connect(m_process, &QProcess::readyReadStandardOutput, this, [this] { + emit readyRead(m_process->readAllStandardOutput(), {}); + }); + connect(m_process, &QProcess::readyReadStandardError, this, [this] { + emit readyRead({}, m_process->readAllStandardError()); + }); + } + ~QProcessImpl() final { ProcessReaper::reap(m_process, m_setup.m_reaperTimeout); } + +private: + qint64 write(const QByteArray &data) final { return m_process->write(data); } + void sendControlSignal(ControlSignal controlSignal) final { + switch (controlSignal) { + case ControlSignal::Terminate: + ProcessHelper::terminateProcess(m_process); + break; + case ControlSignal::Kill: + m_process->kill(); + break; + case ControlSignal::Interrupt: + ProcessHelper::interruptProcess(m_process); + break; + case ControlSignal::KickOff: + QTC_CHECK(false); + break; + case ControlSignal::CloseWriteChannel: + m_process->closeWriteChannel(); + break; + } + } + + virtual ProcessBlockingInterface *processBlockingInterface() const { return m_blockingImpl; } + + void doDefaultStart(const QString &program, const QStringList &arguments) final + { + QTC_ASSERT(QThread::currentThread()->eventDispatcher(), + qWarning("QtcProcess::start(): Starting a process in a non QThread thread " + "may cause infinite hang when destroying the running process.")); + ProcessStartHandler *handler = m_process->processStartHandler(); + handler->setProcessMode(m_setup.m_processMode); + handler->setWriteData(m_setup.m_writeData); + handler->setNativeArguments(m_setup.m_nativeArguments); + handler->setWindowsSpecificStartupFlags(m_setup.m_belowNormalPriority, + m_setup.m_createConsoleOnWindows); + + const QProcessEnvironment penv = m_setup.m_environment.toProcessEnvironment(); + if (!penv.isEmpty()) + m_process->setProcessEnvironment(penv); + m_process->setWorkingDirectory(m_setup.m_workingDirectory.path()); + m_process->setStandardInputFile(m_setup.m_standardInputFile); + m_process->setProcessChannelMode(m_setup.m_processChannelMode); + if (m_setup.m_lowPriority) + m_process->setLowPriority(); + if (m_setup.m_unixTerminalDisabled) + m_process->setUnixTerminalDisabled(); + m_process->setUseCtrlCStub(m_setup.m_useCtrlCStub); + m_process->start(program, arguments, handler->openMode()); + handler->handleProcessStart(); + } + + void handleStarted() + { + m_process->processStartHandler()->handleProcessStarted(); + emit started(m_process->processId()); + } + + void handleError(QProcess::ProcessError error) + { + if (error != QProcess::FailedToStart) + return; + const ProcessResultData result = { m_process->exitCode(), m_process->exitStatus(), + error, m_process->errorString() }; + emit done(result); + } + + void handleFinished(int exitCode, QProcess::ExitStatus exitStatus) + { + const ProcessResultData result = { exitCode, exitStatus, + m_process->error(), m_process->errorString() }; + emit done(result); + } + + ProcessHelper *m_process = nullptr; + QProcessBlockingImpl *m_blockingImpl = nullptr; +}; + +static uint uniqueToken() +{ + static std::atomic_uint globalUniqueToken = 0; + return ++globalUniqueToken; +} + +class ProcessLauncherBlockingImpl : public ProcessBlockingInterface +{ +public: + ProcessLauncherBlockingImpl(CallerHandle *caller) : m_caller(caller) {} + +private: + bool waitForSignal(ProcessSignalType signalType, int msecs) final + { + // TODO: Remove CallerHandle::SignalType + const CallerHandle::SignalType type = [signalType] { + switch (signalType) { + case ProcessSignalType::Started: + return CallerHandle::SignalType::Started; + case ProcessSignalType::ReadyRead: + return CallerHandle::SignalType::ReadyRead; + case ProcessSignalType::Done: + return CallerHandle::SignalType::Done; + } + QTC_CHECK(false); + return CallerHandle::SignalType::NoSignal; + }(); + return m_caller->waitForSignal(type, msecs); + } + + CallerHandle *m_caller = nullptr; +}; + +class ProcessLauncherImpl final : public DefaultImpl +{ + Q_OBJECT +public: + ProcessLauncherImpl() : m_token(uniqueToken()) + { + m_handle = LauncherInterface::registerHandle(this, token()); + m_handle->setProcessSetupData(&m_setup); + connect(m_handle, &CallerHandle::started, + this, &ProcessInterface::started); + connect(m_handle, &CallerHandle::readyRead, + this, &ProcessInterface::readyRead); + connect(m_handle, &CallerHandle::done, + this, &ProcessInterface::done); + m_blockingImpl = new ProcessLauncherBlockingImpl(m_handle); + } + ~ProcessLauncherImpl() final + { + m_handle->close(); + LauncherInterface::unregisterHandle(token()); + m_handle = nullptr; + } + +private: + qint64 write(const QByteArray &data) final { return m_handle->write(data); } + void sendControlSignal(ControlSignal controlSignal) final { + switch (controlSignal) { + case ControlSignal::Terminate: + m_handle->terminate(); + break; + case ControlSignal::Kill: + m_handle->kill(); + break; + case ControlSignal::Interrupt: + ProcessHelper::interruptPid(m_handle->processId()); + break; + case ControlSignal::KickOff: + QTC_CHECK(false); + break; + case ControlSignal::CloseWriteChannel: + m_handle->closeWriteChannel(); + break; + } + } + + virtual ProcessBlockingInterface *processBlockingInterface() const { return m_blockingImpl; } + + void doDefaultStart(const QString &program, const QStringList &arguments) final + { + m_handle->start(program, arguments); + } + + quintptr token() const { return m_token; } + + const uint m_token = 0; + // Lives in caller's thread. + CallerHandle *m_handle = nullptr; + ProcessLauncherBlockingImpl *m_blockingImpl = nullptr; +}; + +static ProcessImpl defaultProcessImpl() +{ + if (qtcEnvironmentVariableIsSet("QTC_USE_QPROCESS")) + return ProcessImpl::QProcess; + return ProcessImpl::ProcessLauncher; +} + +class ProcessInterfaceSignal +{ +public: + ProcessSignalType signalType() const { return m_signalType; } + virtual ~ProcessInterfaceSignal() = default; +protected: + ProcessInterfaceSignal(ProcessSignalType signalType) : m_signalType(signalType) {} +private: + const ProcessSignalType m_signalType; +}; + +class StartedSignal : public ProcessInterfaceSignal +{ +public: + StartedSignal(qint64 processId, qint64 applicationMainThreadId) + : ProcessInterfaceSignal(ProcessSignalType::Started) + , m_processId(processId) + , m_applicationMainThreadId(applicationMainThreadId) {} + qint64 processId() const { return m_processId; } + qint64 applicationMainThreadId() const { return m_applicationMainThreadId; } +private: + const qint64 m_processId; + const qint64 m_applicationMainThreadId; +}; + +class ReadyReadSignal : public ProcessInterfaceSignal +{ +public: + ReadyReadSignal(const QByteArray &stdOut, const QByteArray &stdErr) + : ProcessInterfaceSignal(ProcessSignalType::ReadyRead) + , m_stdOut(stdOut) + , m_stdErr(stdErr) {} + QByteArray stdOut() const { return m_stdOut; } + QByteArray stdErr() const { return m_stdErr; } +private: + const QByteArray m_stdOut; + const QByteArray m_stdErr; +}; + +class DoneSignal : public ProcessInterfaceSignal +{ +public: + DoneSignal(const ProcessResultData &resultData) + : ProcessInterfaceSignal(ProcessSignalType::Done) + , m_resultData(resultData) {} + ProcessResultData resultData() const { return m_resultData; } +private: + const ProcessResultData m_resultData; +}; + +class GeneralProcessBlockingImpl; + +class ProcessInterfaceHandler : public QObject +{ +public: + ProcessInterfaceHandler(GeneralProcessBlockingImpl *caller, ProcessInterface *process); + + // Called from caller's thread exclusively. + bool waitForSignal(ProcessSignalType newSignal, int msecs); + void moveToCallerThread(); + +private: + // Called from caller's thread exclusively. + bool doWaitForSignal(QDeadlineTimer deadline); + + // Called from caller's thread when not waiting for signal, + // otherwise called from temporary thread. + void handleStarted(qint64 processId, qint64 applicationMainThreadId); + void handleReadyRead(const QByteArray &outputData, const QByteArray &errorData); + void handleDone(const ProcessResultData &data); + void appendSignal(ProcessInterfaceSignal *newSignal); + + GeneralProcessBlockingImpl *m_caller = nullptr; + QMutex m_mutex; + QWaitCondition m_waitCondition; +}; + +class GeneralProcessBlockingImpl : public ProcessBlockingInterface +{ +public: + GeneralProcessBlockingImpl(QtcProcessPrivate *parent); + + void flush() { flushSignals(takeAllSignals()); } + bool flushFor(ProcessSignalType signalType) { + return flushSignals(takeSignalsFor(signalType), &signalType); + } + + bool shouldFlush() const { QMutexLocker locker(&m_mutex); return !m_signals.isEmpty(); } + // Called from ProcessInterfaceHandler thread exclusively. + void appendSignal(ProcessInterfaceSignal *launcherSignal); + +private: + // Called from caller's thread exclusively + bool waitForSignal(ProcessSignalType newSignal, int msecs) final; + + QList takeAllSignals(); + QList takeSignalsFor(ProcessSignalType signalType); + bool flushSignals(const QList &signalList, + ProcessSignalType *signalType = nullptr); + + void handleStartedSignal(const StartedSignal *launcherSignal); + void handleReadyReadSignal(const ReadyReadSignal *launcherSignal); + void handleDoneSignal(const DoneSignal *launcherSignal); + + QtcProcessPrivate *m_caller = nullptr; + std::unique_ptr m_processHandler; + mutable QMutex m_mutex; + QList m_signals; +}; + +class QtcProcessPrivate : public QObject +{ +public: + explicit QtcProcessPrivate(Process *parent) + : QObject(parent) + , q(parent) + , m_killTimer(this) + { + m_killTimer.setSingleShot(true); + connect(&m_killTimer, &QTimer::timeout, this, [this] { + m_killTimer.stop(); + sendControlSignal(ControlSignal::Kill); + }); + setupDebugLog(); + } + + void setupDebugLog(); + void storeEventLoopDebugInfo(const QVariant &value); + + ProcessInterface *createProcessInterface() + { + if (m_setup.m_ptyData) + return new PtyProcessImpl; + if (m_setup.m_terminalMode != TerminalMode::Off) + return Terminal::Hooks::instance().createTerminalProcessInterface(); + + const ProcessImpl impl = m_setup.m_processImpl == ProcessImpl::Default + ? defaultProcessImpl() : m_setup.m_processImpl; + if (impl == ProcessImpl::QProcess) + return new QProcessImpl; + return new ProcessLauncherImpl; + } + + void setProcessInterface(ProcessInterface *process) + { + if (m_process) + m_process->disconnect(); + m_process.reset(process); + m_process->setParent(this); + connect(m_process.get(), &ProcessInterface::started, + this, &QtcProcessPrivate::handleStarted); + connect(m_process.get(), &ProcessInterface::readyRead, + this, &QtcProcessPrivate::handleReadyRead); + connect(m_process.get(), &ProcessInterface::done, + this, &QtcProcessPrivate::handleDone); + + m_blockingInterface.reset(process->processBlockingInterface()); + if (!m_blockingInterface) + m_blockingInterface.reset(new GeneralProcessBlockingImpl(this)); + m_blockingInterface->setParent(this); + } + + CommandLine fullCommandLine() const + { + if (!m_setup.m_runAsRoot || HostOsInfo::isWindowsHost()) + return m_setup.m_commandLine; + CommandLine rootCommand("sudo", {"-A"}); + rootCommand.addCommandLineAsArgs(m_setup.m_commandLine); + return rootCommand; + } + + Process *q; + std::unique_ptr m_blockingInterface; + std::unique_ptr m_process; + ProcessSetupData m_setup; + + void slotTimeout(); + void handleStarted(qint64 processId, qint64 applicationMainThreadId); + void handleReadyRead(const QByteArray &outputData, const QByteArray &errorData); + void handleDone(const ProcessResultData &data); + void clearForRun(); + + void emitGuardedSignal(void (Process::* signalName)()) { + GuardLocker locker(m_guard); + emit (q->*signalName)(); + } + + ProcessResult interpretExitCode(int exitCode); + + bool waitForSignal(ProcessSignalType signalType, int msecs); + Qt::ConnectionType connectionType() const; + void sendControlSignal(ControlSignal controlSignal); + + QTimer m_killTimer; + QProcess::ProcessState m_state = QProcess::NotRunning; + qint64 m_processId = 0; + qint64 m_applicationMainThreadId = 0; + ProcessResultData m_resultData; + + QTextCodec *m_codec = QTextCodec::codecForLocale(); + QEventLoop *m_eventLoop = nullptr; + ProcessResult m_result = ProcessResult::StartFailed; + ChannelBuffer m_stdOut; + ChannelBuffer m_stdErr; + ExitCodeInterpreter m_exitCodeInterpreter; + + int m_hangTimerCount = 0; + int m_maxHangTimerCount = defaultMaxHangTimerCount; + bool m_timeOutMessageBoxEnabled = false; + bool m_waitingForUser = false; + + Guard m_guard; +}; + +ProcessInterfaceHandler::ProcessInterfaceHandler(GeneralProcessBlockingImpl *caller, + ProcessInterface *process) + : m_caller(caller) +{ + process->disconnect(); + connect(process, &ProcessInterface::started, + this, &ProcessInterfaceHandler::handleStarted); + connect(process, &ProcessInterface::readyRead, + this, &ProcessInterfaceHandler::handleReadyRead); + connect(process, &ProcessInterface::done, + this, &ProcessInterfaceHandler::handleDone); +} + +// Called from caller's thread exclusively. +bool ProcessInterfaceHandler::waitForSignal(ProcessSignalType newSignal, int msecs) +{ + QDeadlineTimer deadline(msecs); + while (true) { + if (deadline.hasExpired()) + break; + if (!doWaitForSignal(deadline)) + break; + // Matching (or Done) signal was flushed + if (m_caller->flushFor(newSignal)) + return true; + // Otherwise continue awaiting (e.g. when ReadyRead came while waitForFinished()) + } + return false; +} + +// Called from caller's thread exclusively. +void ProcessInterfaceHandler::moveToCallerThread() +{ + QMetaObject::invokeMethod(this, [this] { + moveToThread(m_caller->thread()); + }, Qt::BlockingQueuedConnection); +} + +// Called from caller's thread exclusively. +bool ProcessInterfaceHandler::doWaitForSignal(QDeadlineTimer deadline) +{ + QMutexLocker locker(&m_mutex); + + // Flush, if we have any stored signals. + // This must be called when holding laucher's mutex locked prior to the call to wait, + // so that it's done atomically. + if (m_caller->shouldFlush()) + return true; + + return m_waitCondition.wait(&m_mutex, deadline); +} + +// Called from ProcessInterfaceHandler thread exclusively +void ProcessInterfaceHandler::handleStarted(qint64 processId, qint64 applicationMainThreadId) +{ + appendSignal(new StartedSignal(processId, applicationMainThreadId)); +} + +// Called from ProcessInterfaceHandler thread exclusively +void ProcessInterfaceHandler::handleReadyRead(const QByteArray &outputData, const QByteArray &errorData) +{ + appendSignal(new ReadyReadSignal(outputData, errorData)); +} + +// Called from ProcessInterfaceHandler thread exclusively +void ProcessInterfaceHandler::handleDone(const ProcessResultData &data) +{ + appendSignal(new DoneSignal(data)); +} + +void ProcessInterfaceHandler::appendSignal(ProcessInterfaceSignal *newSignal) +{ + { + QMutexLocker locker(&m_mutex); + m_caller->appendSignal(newSignal); + } + m_waitCondition.wakeOne(); + // call in callers thread + QMetaObject::invokeMethod(m_caller, &GeneralProcessBlockingImpl::flush); +} + +GeneralProcessBlockingImpl::GeneralProcessBlockingImpl(QtcProcessPrivate *parent) + : m_caller(parent) + , m_processHandler(new ProcessInterfaceHandler(this, parent->m_process.get())) +{ + // In order to move the process interface into another thread together with handle + parent->m_process.get()->setParent(m_processHandler.get()); + m_processHandler->setParent(this); + // So the hierarchy looks like: + // QtcProcessPrivate + // | + // +- GeneralProcessBlockingImpl + // | + // +- ProcessInterfaceHandler + // | + // +- ProcessInterface +} + +bool GeneralProcessBlockingImpl::waitForSignal(ProcessSignalType newSignal, int msecs) +{ + m_processHandler->setParent(nullptr); + + QThread thread; + thread.start(); + // Note: the thread may have started before and it's appending new signals before + // waitForSignal() is called. However, in this case they won't be flushed since + // the caller here is blocked, so all signals should be buffered and we are going + // to flush them from inside waitForSignal(). + m_processHandler->moveToThread(&thread); + const bool result = m_processHandler->waitForSignal(newSignal, msecs); + m_processHandler->moveToCallerThread(); + m_processHandler->setParent(this); + thread.quit(); + thread.wait(); + return result; +} + +// Called from caller's thread exclusively +QList GeneralProcessBlockingImpl::takeAllSignals() +{ + QMutexLocker locker(&m_mutex); + return std::exchange(m_signals, {}); +} + +// Called from caller's thread exclusively +QList GeneralProcessBlockingImpl::takeSignalsFor(ProcessSignalType signalType) +{ + // If we are flushing for ReadyRead or Done - flush all. + if (signalType != ProcessSignalType::Started) + return takeAllSignals(); + + QMutexLocker locker(&m_mutex); + const QList storedSignals = transform(std::as_const(m_signals), + [](const ProcessInterfaceSignal *aSignal) { + return aSignal->signalType(); + }); + + // If we are flushing for Started: + // - if Started was buffered - flush Started only (even when Done was buffered) + // - otherwise if Done signal was buffered - flush all. + if (!storedSignals.contains(ProcessSignalType::Started) + && storedSignals.contains(ProcessSignalType::Done)) { + return std::exchange(m_signals, {}); // avoid takeAllSignals() because of mutex locked + } + + QList oldSignals; + const auto matchingIndex = storedSignals.lastIndexOf(signalType); + if (matchingIndex >= 0) { + oldSignals = m_signals.mid(0, matchingIndex + 1); + m_signals = m_signals.mid(matchingIndex + 1); + } + return oldSignals; +} + +// Called from caller's thread exclusively +bool GeneralProcessBlockingImpl::flushSignals(const QList &signalList, + ProcessSignalType *signalType) +{ + bool signalMatched = false; + for (const ProcessInterfaceSignal *storedSignal : std::as_const(signalList)) { + const ProcessSignalType storedSignalType = storedSignal->signalType(); + if (signalType && storedSignalType == *signalType) + signalMatched = true; + switch (storedSignalType) { + case ProcessSignalType::Started: + handleStartedSignal(static_cast(storedSignal)); + break; + case ProcessSignalType::ReadyRead: + handleReadyReadSignal(static_cast(storedSignal)); + break; + case ProcessSignalType::Done: + if (signalType) + signalMatched = true; + handleDoneSignal(static_cast(storedSignal)); + break; + } + delete storedSignal; + } + return signalMatched; +} + +void GeneralProcessBlockingImpl::handleStartedSignal(const StartedSignal *aSignal) +{ + m_caller->handleStarted(aSignal->processId(), aSignal->applicationMainThreadId()); +} + +void GeneralProcessBlockingImpl::handleReadyReadSignal(const ReadyReadSignal *aSignal) +{ + m_caller->handleReadyRead(aSignal->stdOut(), aSignal->stdErr()); +} + +void GeneralProcessBlockingImpl::handleDoneSignal(const DoneSignal *aSignal) +{ + m_caller->handleDone(aSignal->resultData()); +} + +// Called from ProcessInterfaceHandler thread exclusively. +void GeneralProcessBlockingImpl::appendSignal(ProcessInterfaceSignal *newSignal) +{ + QMutexLocker locker(&m_mutex); + m_signals.append(newSignal); +} + +bool QtcProcessPrivate::waitForSignal(ProcessSignalType newSignal, int msecs) +{ + const QDeadlineTimer timeout(msecs); + const QDeadlineTimer currentKillTimeout(m_killTimer.remainingTime()); + const bool needsSplit = m_killTimer.isActive() ? timeout > currentKillTimeout : false; + const QDeadlineTimer mainTimeout = needsSplit ? currentKillTimeout : timeout; + + bool result = m_blockingInterface->waitForSignal(newSignal, mainTimeout.remainingTime()); + if (!result && needsSplit) { + m_killTimer.stop(); + sendControlSignal(ControlSignal::Kill); + result = m_blockingInterface->waitForSignal(newSignal, timeout.remainingTime()); + } + return result; +} + +Qt::ConnectionType QtcProcessPrivate::connectionType() const +{ + return (m_process->thread() == thread()) ? Qt::DirectConnection + : Qt::BlockingQueuedConnection; +} + +void QtcProcessPrivate::sendControlSignal(ControlSignal controlSignal) +{ + QTC_ASSERT(QThread::currentThread() == thread(), return); + if (!m_process || (m_state == QProcess::NotRunning)) + return; + + if (controlSignal == ControlSignal::Terminate || controlSignal == ControlSignal::Kill) + m_resultData.m_canceledByUser = true; + + QMetaObject::invokeMethod(m_process.get(), [this, controlSignal] { + m_process->sendControlSignal(controlSignal); + }, connectionType()); +} + +void QtcProcessPrivate::clearForRun() +{ + m_hangTimerCount = 0; + m_stdOut.clearForRun(); + m_stdOut.codec = m_codec; + m_stdErr.clearForRun(); + m_stdErr.codec = m_codec; + m_result = ProcessResult::StartFailed; + + m_killTimer.stop(); + m_state = QProcess::NotRunning; + m_processId = 0; + m_applicationMainThreadId = 0; + m_resultData = {}; +} + +ProcessResult QtcProcessPrivate::interpretExitCode(int exitCode) +{ + if (m_exitCodeInterpreter) + return m_exitCodeInterpreter(exitCode); + + // default: + return exitCode ? ProcessResult::FinishedWithError : ProcessResult::FinishedWithSuccess; +} + +} // Internal + +/*! + \class Utils::QtcProcess + + \brief The QtcProcess class provides functionality for with processes. + + \sa Utils::ProcessArgs +*/ + +Process::Process(QObject *parent) + : QObject(parent), + d(new QtcProcessPrivate(this)) +{ + qRegisterMetaType("ProcessResultData"); + static int qProcessExitStatusMeta = qRegisterMetaType(); + static int qProcessProcessErrorMeta = qRegisterMetaType(); + Q_UNUSED(qProcessExitStatusMeta) + Q_UNUSED(qProcessProcessErrorMeta) +} + +Process::~Process() +{ + QTC_ASSERT(!d->m_guard.isLocked(), qWarning("Deleting QtcProcess instance directly from " + "one of its signal handlers will lead to crash!")); + if (d->m_process) + d->m_process->disconnect(); + delete d; +} + +void Process::setProcessImpl(ProcessImpl processImpl) +{ + d->m_setup.m_processImpl = processImpl; +} + +void Process::setPtyData(const std::optional &data) +{ + d->m_setup.m_ptyData = data; +} + +std::optional Process::ptyData() const +{ + return d->m_setup.m_ptyData; +} + +ProcessMode Process::processMode() const +{ + return d->m_setup.m_processMode; +} + +void Process::setTerminalMode(TerminalMode mode) +{ + d->m_setup.m_terminalMode = mode; +} + +TerminalMode Process::terminalMode() const +{ + return d->m_setup.m_terminalMode; +} + +void Process::setProcessMode(ProcessMode processMode) +{ + d->m_setup.m_processMode = processMode; +} + +void Process::setEnvironment(const Environment &env) +{ + d->m_setup.m_environment = env; +} + +const Environment &Process::environment() const +{ + return d->m_setup.m_environment; +} + +void Process::setControlEnvironment(const Environment &environment) +{ + d->m_setup.m_controlEnvironment = environment; +} + +const Environment &Process::controlEnvironment() const +{ + return d->m_setup.m_controlEnvironment; +} + +void Process::setCommand(const CommandLine &cmdLine) +{ + if (d->m_setup.m_workingDirectory.needsDevice() && cmdLine.executable().needsDevice()) { + QTC_CHECK(d->m_setup.m_workingDirectory.host() == cmdLine.executable().host()); + } + d->m_setup.m_commandLine = cmdLine; +} + +const CommandLine &Process::commandLine() const +{ + return d->m_setup.m_commandLine; +} + +FilePath Process::workingDirectory() const +{ + return d->m_setup.m_workingDirectory; +} + +void Process::setWorkingDirectory(const FilePath &dir) +{ + if (dir.needsDevice() && d->m_setup.m_commandLine.executable().needsDevice()) { + QTC_CHECK(dir.host() == d->m_setup.m_commandLine.executable().host()); + } + d->m_setup.m_workingDirectory = dir; +} + +void Process::setUseCtrlCStub(bool enabled) +{ + d->m_setup.m_useCtrlCStub = enabled; +} + +void Process::start() +{ + QTC_ASSERT(state() == QProcess::NotRunning, return); + QTC_ASSERT(!(d->m_process && d->m_guard.isLocked()), + qWarning("Restarting the QtcProcess directly from one of its signal handlers will " + "lead to crash! Consider calling close() prior to direct restart.")); + d->clearForRun(); + ProcessInterface *processImpl = nullptr; + if (d->m_setup.m_commandLine.executable().needsDevice()) { + QTC_ASSERT(s_deviceHooks.processImplHook, return); + processImpl = s_deviceHooks.processImplHook(commandLine().executable()); + } else { + processImpl = d->createProcessInterface(); + } + QTC_ASSERT(processImpl, return); + d->setProcessInterface(processImpl); + d->m_state = QProcess::Starting; + d->m_process->m_setup = d->m_setup; + d->m_process->m_setup.m_commandLine = d->fullCommandLine(); + d->emitGuardedSignal(&Process::starting); + d->m_process->start(); +} + +void Process::terminate() +{ + d->sendControlSignal(ControlSignal::Terminate); +} + +void Process::kill() +{ + d->sendControlSignal(ControlSignal::Kill); +} + +void Process::interrupt() +{ + d->sendControlSignal(ControlSignal::Interrupt); +} + +void Process::kickoffProcess() +{ + d->sendControlSignal(ControlSignal::KickOff); +} + +void Process::closeWriteChannel() +{ + d->sendControlSignal(ControlSignal::CloseWriteChannel); +} + +bool Process::startDetached(const CommandLine &cmd, const FilePath &workingDirectory, qint64 *pid) +{ + return QProcess::startDetached(cmd.executable().toUserOutput(), + cmd.splitArguments(), + workingDirectory.toUserOutput(), + pid); +} + +void Process::setLowPriority() +{ + d->m_setup.m_lowPriority = true; +} + +void Process::setDisableUnixTerminal() +{ + d->m_setup.m_unixTerminalDisabled = true; +} + +void Process::setAbortOnMetaChars(bool abort) +{ + d->m_setup.m_abortOnMetaChars = abort; +} + +void Process::setRunAsRoot(bool on) +{ + d->m_setup.m_runAsRoot = on; +} + +bool Process::isRunAsRoot() const +{ + return d->m_setup.m_runAsRoot; +} + +void Process::setStandardInputFile(const QString &inputFile) +{ + d->m_setup.m_standardInputFile = inputFile; +} + +QString Process::toStandaloneCommandLine() const +{ + QStringList parts; + parts.append("/usr/bin/env"); + if (!d->m_setup.m_workingDirectory.isEmpty()) { + parts.append("-C"); + d->m_setup.m_workingDirectory.path(); + } + parts.append("-i"); + if (d->m_setup.m_environment.hasChanges()) { + const QStringList envVars = d->m_setup.m_environment.toStringList(); + std::transform(envVars.cbegin(), envVars.cend(), + std::back_inserter(parts), ProcessArgs::quoteArgUnix); + } + parts.append(d->m_setup.m_commandLine.executable().path()); + parts.append(d->m_setup.m_commandLine.splitArguments()); + return parts.join(" "); +} + +void Process::setCreateConsoleOnWindows(bool create) +{ + d->m_setup.m_createConsoleOnWindows = create; +} + +bool Process::createConsoleOnWindows() const +{ + return d->m_setup.m_createConsoleOnWindows; +} + +void Process::setExtraData(const QString &key, const QVariant &value) +{ + d->m_setup.m_extraData.insert(key, value); +} + +QVariant Process::extraData(const QString &key) const +{ + return d->m_setup.m_extraData.value(key); +} + +void Process::setExtraData(const QVariantHash &extraData) +{ + d->m_setup.m_extraData = extraData; +} + +QVariantHash Process::extraData() const +{ + return d->m_setup.m_extraData; +} + +void Process::setReaperTimeout(int msecs) +{ + d->m_setup.m_reaperTimeout = msecs; +} + +int Process::reaperTimeout() const +{ + return d->m_setup.m_reaperTimeout; +} + +void Process::setRemoteProcessHooks(const DeviceProcessHooks &hooks) +{ + s_deviceHooks = hooks; +} + +static bool askToKill(const CommandLine &command) +{ +#ifdef QT_GUI_LIB + if (!isMainThread()) + return true; + const QString title = Tr::tr("Process Not Responding"); + QString msg = command.isEmpty() ? Tr::tr("The process is not responding.") + : Tr::tr("The process \"%1\" is not responding.") + .arg(command.executable().toUserOutput()); + msg += ' '; + msg += Tr::tr("Terminate the process?"); + // Restore the cursor that is set to wait while running. + const bool hasOverrideCursor = QApplication::overrideCursor() != nullptr; + if (hasOverrideCursor) + QApplication::restoreOverrideCursor(); + QMessageBox::StandardButton answer = QMessageBox::question(nullptr, title, msg, QMessageBox::Yes|QMessageBox::No); + if (hasOverrideCursor) + QApplication::setOverrideCursor(Qt::WaitCursor); + return answer == QMessageBox::Yes; +#else + Q_UNUSED(command) + return true; +#endif +} + +// Helper for running a process synchronously in the foreground with timeout +// detection (taking effect after no more output +// occurs on stderr/stdout as opposed to waitForFinished()). Returns false if a timeout +// occurs. Checking of the process' exit state/code still has to be done. + +bool Process::readDataFromProcess(QByteArray *stdOut, QByteArray *stdErr, int timeoutS) +{ + enum { syncDebug = 0 }; + if (syncDebug) + qDebug() << ">readDataFromProcess" << timeoutS; + if (state() != QProcess::Running) { + qWarning("readDataFromProcess: Process in non-running state passed in."); + return false; + } + + // Keep the process running until it has no longer has data + bool finished = false; + bool hasData = false; + do { + finished = waitForFinished(timeoutS > 0 ? timeoutS * 1000 : -1) + || state() == QProcess::NotRunning; + // First check 'stdout' + const QByteArray newStdOut = readAllRawStandardOutput(); + if (!newStdOut.isEmpty()) { + hasData = true; + if (stdOut) + stdOut->append(newStdOut); + } + // Check 'stderr' separately. This is a special handling + // for 'git pull' and the like which prints its progress on stderr. + const QByteArray newStdErr = readAllRawStandardError(); + if (!newStdErr.isEmpty()) { + hasData = true; + if (stdErr) + stdErr->append(newStdErr); + } + // Prompt user, pretend we have data if says 'No'. + const bool hang = !hasData && !finished; + hasData = hang && !askToKill(d->m_setup.m_commandLine); + } while (hasData && !finished); + if (syncDebug) + qDebug() << "m_result; +} + +ProcessResultData Process::resultData() const +{ + return d->m_resultData; +} + +int Process::exitCode() const +{ + return resultData().m_exitCode; +} + +QProcess::ExitStatus Process::exitStatus() const +{ + return resultData().m_exitStatus; +} + +QProcess::ProcessError Process::error() const +{ + return resultData().m_error; +} + +QString Process::errorString() const +{ + return resultData().m_errorString; +} + +// Path utilities + +Environment Process::systemEnvironmentForBinary(const FilePath &filePath) +{ + if (filePath.needsDevice()) { + QTC_ASSERT(s_deviceHooks.systemEnvironmentForBinary, return {}); + return s_deviceHooks.systemEnvironmentForBinary(filePath); + } + + return Environment::systemEnvironment(); +} + +qint64 Process::applicationMainThreadId() const +{ + return d->m_applicationMainThreadId; +} + +QProcess::ProcessChannelMode Process::processChannelMode() const +{ + return d->m_setup.m_processChannelMode; +} + +void Process::setProcessChannelMode(QProcess::ProcessChannelMode mode) +{ + d->m_setup.m_processChannelMode = mode; +} + +QProcess::ProcessState Process::state() const +{ + return d->m_state; +} + +bool Process::isRunning() const +{ + return state() == QProcess::Running; +} + +qint64 Process::processId() const +{ + return d->m_processId; +} + +bool Process::waitForStarted(int msecs) +{ + QTC_ASSERT(d->m_process, return false); + if (d->m_state == QProcess::Running) + return true; + if (d->m_state == QProcess::NotRunning) + return false; + return s_waitForStarted.measureAndRun(&QtcProcessPrivate::waitForSignal, d, + ProcessSignalType::Started, msecs); +} + +bool Process::waitForReadyRead(int msecs) +{ + QTC_ASSERT(d->m_process, return false); + if (d->m_state == QProcess::NotRunning) + return false; + return d->waitForSignal(ProcessSignalType::ReadyRead, msecs); +} + +bool Process::waitForFinished(int msecs) +{ + QTC_ASSERT(d->m_process, return false); + if (d->m_state == QProcess::NotRunning) + return false; + return d->waitForSignal(ProcessSignalType::Done, msecs); +} + +QByteArray Process::readAllRawStandardOutput() +{ + return d->m_stdOut.readAllData(); +} + +QByteArray Process::readAllRawStandardError() +{ + return d->m_stdErr.readAllData(); +} + +qint64 Process::write(const QString &input) +{ + // Non-windows is assumed to be UTF-8 + if (commandLine().executable().osType() != OsTypeWindows) + return writeRaw(input.toUtf8()); + + if (HostOsInfo::hostOs() == OsTypeWindows) + return writeRaw(input.toLocal8Bit()); + + // "remote" Windows target on non-Windows host is unlikely, + // but the true encoding is not accessible. Use UTF8 as best guess. + QTC_CHECK(false); + return writeRaw(input.toUtf8()); +} + +qint64 Process::writeRaw(const QByteArray &input) +{ + QTC_ASSERT(processMode() == ProcessMode::Writer, return -1); + QTC_ASSERT(d->m_process, return -1); + QTC_ASSERT(state() == QProcess::Running, return -1); + QTC_ASSERT(QThread::currentThread() == thread(), return -1); + qint64 result = -1; + QMetaObject::invokeMethod(d->m_process.get(), [this, input] { + d->m_process->write(input); + }, d->connectionType(), &result); + return result; +} + +void Process::close() +{ + QTC_ASSERT(QThread::currentThread() == thread(), return); + if (d->m_process) { + // Note: the m_process may be inside ProcessInterfaceHandler's thread. + QTC_ASSERT(d->m_process->thread() == thread(), return); + d->m_process->disconnect(); + d->m_process.release()->deleteLater(); + } + if (d->m_blockingInterface) { + d->m_blockingInterface->disconnect(); + d->m_blockingInterface.release()->deleteLater(); + } + d->clearForRun(); +} + +/* + Calls terminate() directly and after a delay of reaperTimeout() it calls kill() + if the process is still running. +*/ +void Process::stop() +{ + if (state() == QProcess::NotRunning) + return; + + d->sendControlSignal(ControlSignal::Terminate); + d->m_killTimer.start(d->m_process->m_setup.m_reaperTimeout); +} + +QString Process::readAllStandardOutput() +{ + return QString::fromUtf8(readAllRawStandardOutput()); +} + +QString Process::readAllStandardError() +{ + return QString::fromUtf8(readAllRawStandardError()); +} + +/*! + \class Utils::SynchronousProcess + + \brief The SynchronousProcess class runs a synchronous process in its own + event loop that blocks only user input events. Thus, it allows for the GUI to + repaint and append output to log windows. + + The callbacks set with setStdOutCallback(), setStdErrCallback() are called + with complete lines based on the '\\n' marker. + They would typically be used for log windows. + + Alternatively you can used setStdOutLineCallback() and setStdErrLineCallback() + to process the output line by line. + + There is a timeout handling that takes effect after the last data have been + read from stdout/stdin (as opposed to waitForFinished(), which measures time + since it was invoked). It is thus also suitable for slow processes that + continuously output data (like version system operations). + + The property timeOutMessageBoxEnabled influences whether a message box is + shown asking the user if they want to kill the process on timeout (default: false). + + There are also static utility functions for dealing with fully synchronous + processes, like reading the output with correct timeout handling. + + Caution: This class should NOT be used if there is a chance that the process + triggers opening dialog boxes (for example, by file watchers triggering), + as this will cause event loop problems. +*/ + +QString Process::exitMessage() const +{ + const QString fullCmd = commandLine().toUserOutput(); + switch (result()) { + case ProcessResult::FinishedWithSuccess: + return Tr::tr("The command \"%1\" finished successfully.").arg(fullCmd); + case ProcessResult::FinishedWithError: + return Tr::tr("The command \"%1\" terminated with exit code %2.") + .arg(fullCmd).arg(exitCode()); + case ProcessResult::TerminatedAbnormally: + return Tr::tr("The command \"%1\" terminated abnormally.").arg(fullCmd); + case ProcessResult::StartFailed: + return Tr::tr("The command \"%1\" could not be started.").arg(fullCmd); + case ProcessResult::Hang: + return Tr::tr("The command \"%1\" did not respond within the timeout limit (%2 s).") + .arg(fullCmd).arg(d->m_maxHangTimerCount); + } + return {}; +} + +QByteArray Process::allRawOutput() const +{ + QTC_CHECK(d->m_stdOut.keepRawData); + QTC_CHECK(d->m_stdErr.keepRawData); + if (!d->m_stdOut.rawData.isEmpty() && !d->m_stdErr.rawData.isEmpty()) { + QByteArray result = d->m_stdOut.rawData; + if (!result.endsWith('\n')) + result += '\n'; + result += d->m_stdErr.rawData; + return result; + } + return !d->m_stdOut.rawData.isEmpty() ? d->m_stdOut.rawData : d->m_stdErr.rawData; +} + +QString Process::allOutput() const +{ + QTC_CHECK(d->m_stdOut.keepRawData); + QTC_CHECK(d->m_stdErr.keepRawData); + const QString out = cleanedStdOut(); + const QString err = cleanedStdErr(); + + if (!out.isEmpty() && !err.isEmpty()) { + QString result = out; + if (!result.endsWith('\n')) + result += '\n'; + result += err; + return result; + } + return !out.isEmpty() ? out : err; +} + +QByteArray Process::rawStdOut() const +{ + QTC_CHECK(d->m_stdOut.keepRawData); + return d->m_stdOut.rawData; +} + +QString Process::stdOut() const +{ + QTC_CHECK(d->m_stdOut.keepRawData); + return d->m_codec->toUnicode(d->m_stdOut.rawData); +} + +QString Process::stdErr() const +{ + QTC_CHECK(d->m_stdErr.keepRawData); + return d->m_codec->toUnicode(d->m_stdErr.rawData); +} + +QString Process::cleanedStdOut() const +{ + return Utils::normalizeNewlines(stdOut()); +} + +QString Process::cleanedStdErr() const +{ + return Utils::normalizeNewlines(stdErr()); +} + +static QStringList splitLines(const QString &text) +{ + QStringList result = text.split('\n'); + for (QString &line : result) { + if (line.endsWith('\r')) + line.chop(1); + } + return result; +} + +const QStringList Process::stdOutLines() const +{ + return splitLines(cleanedStdOut()); +} + +const QStringList Process::stdErrLines() const +{ + return splitLines(cleanedStdErr()); +} + +QTCREATOR_UTILS_EXPORT QDebug operator<<(QDebug str, const Process &r) +{ + QDebug nsp = str.nospace(); + nsp << "QtcProcess: result=" + << int(r.d->m_result) << " ex=" << r.exitCode() << '\n' + << r.d->m_stdOut.rawData.size() << " bytes stdout, stderr=" << r.d->m_stdErr.rawData << '\n'; + return str; +} + +void ChannelBuffer::clearForRun() +{ + rawData.clear(); + codecState.reset(new QTextCodec::ConverterState); + incompleteLineBuffer.clear(); +} + +/* Check for complete lines read from the device and return them, moving the + * buffer position. */ +void ChannelBuffer::append(const QByteArray &text) +{ + if (text.isEmpty()) + return; + + if (keepRawData) + rawData += text; + + // Line-wise operation below: + if (!outputCallback) + return; + + // Convert and append the new input to the buffer of incomplete lines + incompleteLineBuffer.append(codec->toUnicode(text.constData(), text.size(), codecState.get())); + + do { + // Any completed lines in the incompleteLineBuffer? + int pos = -1; + if (emitSingleLines) { + const int posn = incompleteLineBuffer.indexOf('\n'); + const int posr = incompleteLineBuffer.indexOf('\r'); + if (posn != -1) { + if (posr != -1) { + if (posn == posr + 1) + pos = posn; // \r followed by \n -> line end, use the \n. + else + pos = qMin(posr, posn); // free floating \r and \n: Use the first one. + } else { + pos = posn; + } + } else { + pos = posr; // Make sure internal '\r' triggers a line output + } + } else { + pos = qMax(incompleteLineBuffer.lastIndexOf('\n'), + incompleteLineBuffer.lastIndexOf('\r')); + } + + if (pos == -1) + break; + + // Get completed lines and remove them from the incompleteLinesBuffer: + const QString line = Utils::normalizeNewlines(incompleteLineBuffer.left(pos + 1)); + incompleteLineBuffer = incompleteLineBuffer.mid(pos + 1); + + QTC_ASSERT(outputCallback, return); + outputCallback(line); + + if (!emitSingleLines) + break; + } while (true); +} + +void ChannelBuffer::handleRest() +{ + if (outputCallback && !incompleteLineBuffer.isEmpty()) { + outputCallback(incompleteLineBuffer); + incompleteLineBuffer.clear(); + } +} + +void Process::setTimeoutS(int timeoutS) +{ + if (timeoutS > 0) + d->m_maxHangTimerCount = qMax(2, timeoutS); + else + d->m_maxHangTimerCount = INT_MAX / 1000; +} + +int Process::timeoutS() const +{ + return d->m_maxHangTimerCount; +} + +void Process::setCodec(QTextCodec *c) +{ + QTC_ASSERT(c, return); + d->m_codec = c; +} + +void Process::setTimeOutMessageBoxEnabled(bool v) +{ + d->m_timeOutMessageBoxEnabled = v; +} + +void Process::setExitCodeInterpreter(const ExitCodeInterpreter &interpreter) +{ + d->m_exitCodeInterpreter = interpreter; +} + +void Process::setWriteData(const QByteArray &writeData) +{ + d->m_setup.m_writeData = writeData; +} + +void Process::runBlocking(EventLoopMode eventLoopMode) +{ + // Attach a dynamic property with info about blocking type + d->storeEventLoopDebugInfo(int(eventLoopMode)); + + QDateTime startTime; + static const int blockingThresholdMs = qtcEnvironmentVariableIntValue("QTC_PROCESS_THRESHOLD"); + if (blockingThresholdMs > 0 && isMainThread()) + startTime = QDateTime::currentDateTime(); + Process::start(); + + // Remove the dynamic property so that it's not reused in subseqent start() + d->storeEventLoopDebugInfo({}); + + if (eventLoopMode == EventLoopMode::On) { + // Start failure is triggered immediately if the executable cannot be found in the path. + // In this case the process is left in NotRunning state. + // Do not start the event loop in that case. + if (state() == QProcess::Starting) { + QTimer timer(this); + connect(&timer, &QTimer::timeout, d, &QtcProcessPrivate::slotTimeout); + timer.setInterval(1000); + timer.start(); +#ifdef QT_GUI_LIB + if (isMainThread()) + QApplication::setOverrideCursor(Qt::WaitCursor); +#endif + QEventLoop eventLoop(this); + QTC_ASSERT(!d->m_eventLoop, return); + d->m_eventLoop = &eventLoop; + eventLoop.exec(QEventLoop::ExcludeUserInputEvents); + d->m_eventLoop = nullptr; + timer.stop(); +#ifdef QT_GUI_LIB + if (isMainThread()) + QApplication::restoreOverrideCursor(); +#endif + } + } else { + if (!waitForStarted(d->m_maxHangTimerCount * 1000)) { + d->m_result = ProcessResult::StartFailed; + return; + } + if (!waitForFinished(d->m_maxHangTimerCount * 1000)) { + d->m_result = ProcessResult::Hang; + terminate(); + if (!waitForFinished(1000)) { + kill(); + waitForFinished(1000); + } + } + } + if (blockingThresholdMs > 0) { + const int timeDiff = startTime.msecsTo(QDateTime::currentDateTime()); + if (timeDiff > blockingThresholdMs && isMainThread()) { + qWarning() << "Blocking process " << d->m_setup.m_commandLine << "took" << timeDiff + << "ms, longer than threshold" << blockingThresholdMs; + } + } +} + +void Process::setStdOutCallback(const TextChannelCallback &callback) +{ + d->m_stdOut.outputCallback = callback; + d->m_stdOut.emitSingleLines = false; +} + +void Process::setStdOutLineCallback(const TextChannelCallback &callback) +{ + d->m_stdOut.outputCallback = callback; + d->m_stdOut.emitSingleLines = true; + d->m_stdOut.keepRawData = false; +} + +void Process::setStdErrCallback(const TextChannelCallback &callback) +{ + d->m_stdErr.outputCallback = callback; + d->m_stdErr.emitSingleLines = false; +} + +void Process::setStdErrLineCallback(const TextChannelCallback &callback) +{ + d->m_stdErr.outputCallback = callback; + d->m_stdErr.emitSingleLines = true; + d->m_stdErr.keepRawData = false; +} + +void Process::setTextChannelMode(Channel channel, TextChannelMode mode) +{ + const TextChannelCallback outputCb = [this](const QString &text) { + GuardLocker locker(d->m_guard); + emit textOnStandardOutput(text); + }; + const TextChannelCallback errorCb = [this](const QString &text) { + GuardLocker locker(d->m_guard); + emit textOnStandardError(text); + }; + const TextChannelCallback callback = (channel == Channel::Output) ? outputCb : errorCb; + ChannelBuffer *buffer = channel == Channel::Output ? &d->m_stdOut : &d->m_stdErr; + QTC_ASSERT(buffer->m_textChannelMode == TextChannelMode::Off, qWarning() + << "QtcProcess::setTextChannelMode(): Changing text channel mode for" + << (channel == Channel::Output ? "Output": "Error") + << "channel while it was previously set for this channel."); + buffer->m_textChannelMode = mode; + switch (mode) { + case TextChannelMode::Off: + buffer->outputCallback = {}; + buffer->emitSingleLines = true; + buffer->keepRawData = true; + break; + case TextChannelMode::SingleLine: + buffer->outputCallback = callback; + buffer->emitSingleLines = true; + buffer->keepRawData = false; + break; + case TextChannelMode::MultiLine: + buffer->outputCallback = callback; + buffer->emitSingleLines = false; + buffer->keepRawData = true; + break; + } +} + +TextChannelMode Process::textChannelMode(Channel channel) const +{ + ChannelBuffer *buffer = channel == Channel::Output ? &d->m_stdOut : &d->m_stdErr; + return buffer->m_textChannelMode; +} + +void QtcProcessPrivate::slotTimeout() +{ + if (!m_waitingForUser && (++m_hangTimerCount > m_maxHangTimerCount)) { + if (debug) + qDebug() << Q_FUNC_INFO << "HANG detected, killing"; + m_waitingForUser = true; + const bool terminate = !m_timeOutMessageBoxEnabled || askToKill(m_setup.m_commandLine); + m_waitingForUser = false; + if (terminate) { + q->stop(); + q->waitForFinished(); + m_result = ProcessResult::Hang; + } else { + m_hangTimerCount = 0; + } + } else { + if (debug) + qDebug() << Q_FUNC_INFO << m_hangTimerCount; + } +} + +void QtcProcessPrivate::handleStarted(qint64 processId, qint64 applicationMainThreadId) +{ + QTC_CHECK(m_state == QProcess::Starting); + m_state = QProcess::Running; + + m_processId = processId; + m_applicationMainThreadId = applicationMainThreadId; + emitGuardedSignal(&Process::started); +} + +void QtcProcessPrivate::handleReadyRead(const QByteArray &outputData, const QByteArray &errorData) +{ + QTC_CHECK(m_state == QProcess::Running); + + // TODO: check why we need this timer? + m_hangTimerCount = 0; + // TODO: store a copy of m_processChannelMode on start()? Currently we assert that state + // is NotRunning when setting the process channel mode. + + if (!outputData.isEmpty()) { + if (m_process->m_setup.m_processChannelMode == QProcess::ForwardedOutputChannel + || m_process->m_setup.m_processChannelMode == QProcess::ForwardedChannels) { + std::cout << outputData.constData() << std::flush; + } else { + m_stdOut.append(outputData); + emitGuardedSignal(&Process::readyReadStandardOutput); + } + } + if (!errorData.isEmpty()) { + if (m_process->m_setup.m_processChannelMode == QProcess::ForwardedErrorChannel + || m_process->m_setup.m_processChannelMode == QProcess::ForwardedChannels) { + std::cerr << errorData.constData() << std::flush; + } else { + m_stdErr.append(errorData); + emitGuardedSignal(&Process::readyReadStandardError); + } + } +} + +void QtcProcessPrivate::handleDone(const ProcessResultData &data) +{ + m_killTimer.stop(); + const bool wasCanceled = m_resultData.m_canceledByUser; + m_resultData = data; + m_resultData.m_canceledByUser = wasCanceled; + + switch (m_state) { + case QProcess::NotRunning: + QTC_CHECK(false); // Can't happen + break; + case QProcess::Starting: + QTC_CHECK(m_resultData.m_error == QProcess::FailedToStart); + break; + case QProcess::Running: + QTC_CHECK(m_resultData.m_error != QProcess::FailedToStart); + break; + } + m_state = QProcess::NotRunning; + + // This code (255) is being returned by QProcess when FailedToStart error occurred + if (m_resultData.m_error == QProcess::FailedToStart) + m_resultData.m_exitCode = 0xFF; + + // HACK: See QIODevice::errorString() implementation. + if (m_resultData.m_error == QProcess::UnknownError) + m_resultData.m_errorString.clear(); + else if (m_result != ProcessResult::Hang) + m_result = ProcessResult::StartFailed; + + if (debug) + qDebug() << Q_FUNC_INFO << m_resultData.m_exitCode << m_resultData.m_exitStatus; + m_hangTimerCount = 0; + + if (m_resultData.m_error != QProcess::FailedToStart) { + switch (m_resultData.m_exitStatus) { + case QProcess::NormalExit: + m_result = interpretExitCode(m_resultData.m_exitCode); + break; + case QProcess::CrashExit: + // Was hang detected before and killed? + if (m_result != ProcessResult::Hang) + m_result = ProcessResult::TerminatedAbnormally; + break; + } + } + if (m_eventLoop) + m_eventLoop->quit(); + + m_stdOut.handleRest(); + m_stdErr.handleRest(); + + emitGuardedSignal(&Process::done); + m_processId = 0; + m_applicationMainThreadId = 0; +} + +static QString blockingMessage(const QVariant &variant) +{ + if (!variant.isValid()) + return "non blocking"; + if (variant.toInt() == int(EventLoopMode::On)) + return "blocking with event loop"; + return "blocking without event loop"; +} + +void QtcProcessPrivate::setupDebugLog() +{ + if (!processLog().isDebugEnabled()) + return; + + auto now = [] { + using namespace std::chrono; + return duration_cast(system_clock::now().time_since_epoch()).count(); + }; + + connect(q, &Process::starting, this, [=] { + const quint64 msNow = now(); + setProperty(QTC_PROCESS_STARTTIME, msNow); + + static std::atomic_int startCounter = 0; + const int currentNumber = startCounter.fetch_add(1); + qCDebug(processLog).nospace().noquote() + << "Process " << currentNumber << " starting (" + << qPrintable(blockingMessage(property(QTC_PROCESS_BLOCKING_TYPE))) + << "): " << m_setup.m_commandLine.toUserOutput(); + setProperty(QTC_PROCESS_NUMBER, currentNumber); + }); + + connect(q, &Process::done, this, [=] { + if (!m_process.get()) + return; + const QVariant n = property(QTC_PROCESS_NUMBER); + if (!n.isValid()) + return; + const quint64 msNow = now(); + const quint64 msStarted = property(QTC_PROCESS_STARTTIME).toULongLong(); + const quint64 msElapsed = msNow - msStarted; + + const int number = n.toInt(); + const QString stdOut = q->cleanedStdOut(); + const QString stdErr = q->cleanedStdErr(); + qCDebug(processLog).nospace() + << "Process " << number << " finished: result=" << int(m_result) + << ", ex=" << m_resultData.m_exitCode + << ", " << stdOut.size() << " bytes stdout: " << stdOut.left(20) + << ", " << stdErr.size() << " bytes stderr: " << stdErr.left(1000) + << ", " << msElapsed << " ms elapsed"; + if (processStdoutLog().isDebugEnabled() && !stdOut.isEmpty()) + qCDebug(processStdoutLog).nospace() << "Process " << number << " sdout: " << stdOut; + if (processStderrLog().isDebugEnabled() && !stdErr.isEmpty()) + qCDebug(processStderrLog).nospace() << "Process " << number << " stderr: " << stdErr; + }); +} + +void QtcProcessPrivate::storeEventLoopDebugInfo(const QVariant &value) +{ + if (processLog().isDebugEnabled()) + setProperty(QTC_PROCESS_BLOCKING_TYPE, value); +} + +ProcessTaskAdapter::ProcessTaskAdapter() +{ + connect(task(), &Process::done, this, [this] { + emit done(task()->result() == ProcessResult::FinishedWithSuccess); + }); +} + +void ProcessTaskAdapter::start() +{ + task()->start(); +} + +} // namespace Utils + +#include "process.moc" diff --git a/src/libs/utils/process.h b/src/libs/utils/process.h new file mode 100644 index 0000000000..f89b6f9b22 --- /dev/null +++ b/src/libs/utils/process.h @@ -0,0 +1,219 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 + +#pragma once + +#include "utils_global.h" + +#include "commandline.h" +#include "processenums.h" +#include "tasktree.h" + +#include + +QT_BEGIN_NAMESPACE +class QDebug; +class QTextCodec; +QT_END_NAMESPACE + +class tst_QtcProcess; + +namespace Utils { + +namespace Internal { class QtcProcessPrivate; } +namespace Pty { class Data; } + +class Environment; +class DeviceProcessHooks; +class ProcessInterface; +class ProcessResultData; + +class QTCREATOR_UTILS_EXPORT Process final : public QObject +{ + Q_OBJECT + +public: + explicit Process(QObject *parent = nullptr); + ~Process(); + + // ProcessInterface related + + void start(); + + void terminate(); + void kill(); + void interrupt(); + void kickoffProcess(); + void closeWriteChannel(); + void close(); + void stop(); + + QString readAllStandardOutput(); + QString readAllStandardError(); + + QByteArray readAllRawStandardOutput(); + QByteArray readAllRawStandardError(); + + qint64 write(const QString &input); + qint64 writeRaw(const QByteArray &input); + + qint64 processId() const; + qint64 applicationMainThreadId() const; + + QProcess::ProcessState state() const; + ProcessResultData resultData() const; + + int exitCode() const; + QProcess::ExitStatus exitStatus() const; + + QProcess::ProcessError error() const; + QString errorString() const; + + bool waitForStarted(int msecs = 30000); + bool waitForReadyRead(int msecs = 30000); + bool waitForFinished(int msecs = 30000); + + // ProcessSetupData related + + void setProcessImpl(ProcessImpl processImpl); + + void setPtyData(const std::optional &data); + std::optional ptyData() const; + + void setTerminalMode(TerminalMode mode); + TerminalMode terminalMode() const; + bool usesTerminal() const { return terminalMode() != TerminalMode::Off; } + + void setProcessMode(ProcessMode processMode); + ProcessMode processMode() const; + + void setEnvironment(const Environment &env); // Main process + const Environment &environment() const; + + void setControlEnvironment(const Environment &env); // Possible helper process (ssh on host etc) + const Environment &controlEnvironment() const; + + void setCommand(const CommandLine &cmdLine); + const CommandLine &commandLine() const; + + void setWorkingDirectory(const FilePath &dir); + FilePath workingDirectory() const; + + void setWriteData(const QByteArray &writeData); + + void setUseCtrlCStub(bool enabled); // release only + void setLowPriority(); + void setDisableUnixTerminal(); + void setRunAsRoot(bool on); + bool isRunAsRoot() const; + void setAbortOnMetaChars(bool abort); + + QProcess::ProcessChannelMode processChannelMode() const; + 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; + + void setReaperTimeout(int msecs); + int reaperTimeout() const; + + 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); + + static bool startDetached(const CommandLine &cmd, const FilePath &workingDirectory = {}, + qint64 *pid = nullptr); + + // Starts the command and waits for finish. + // User input processing is enabled when EventLoopMode::On was passed. + void runBlocking(EventLoopMode eventLoopMode = EventLoopMode::Off); + + /* Timeout for hanging processes (triggers after no more output + * occurs on stderr/stdout). */ + void setTimeoutS(int timeoutS); + int timeoutS() const; + + // TODO: We should specify the purpose of the codec, e.g. setCodecForStandardChannel() + void setCodec(QTextCodec *c); + void setTimeOutMessageBoxEnabled(bool); + void setExitCodeInterpreter(const ExitCodeInterpreter &interpreter); + + 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; + + bool readDataFromProcess(QByteArray *stdOut, QByteArray *stdErr, int timeoutS = 30); + + ProcessResult result() const; + + QByteArray allRawOutput() const; + QString allOutput() const; + + QByteArray rawStdOut() const; + + QString stdOut() const; // possibly with CR + QString stdErr() const; // possibly with CR + + 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 + + const QStringList stdOutLines() const; // split, CR removed + const QStringList stdErrLines() const; // split, CR removed + + QString exitMessage() const; + + QString toStandaloneCommandLine() const; + + void setCreateConsoleOnWindows(bool create); + bool createConsoleOnWindows() const; + +signals: + void starting(); // On NotRunning -> Starting state transition + void started(); // On Starting -> Running state transition + void done(); // On Starting | Running -> NotRunning state transition + void readyReadStandardOutput(); + void readyReadStandardError(); + void textOnStandardOutput(const QString &text); + void textOnStandardError(const QString &text); + +private: + friend QTCREATOR_UTILS_EXPORT QDebug operator<<(QDebug str, const Process &r); + + friend class Internal::QtcProcessPrivate; + Internal::QtcProcessPrivate *d = nullptr; +}; + +class DeviceProcessHooks +{ +public: + std::function processImplHook; + std::function systemEnvironmentForBinary; +}; + +class QTCREATOR_UTILS_EXPORT ProcessTaskAdapter : public Tasking::TaskAdapter +{ +public: + ProcessTaskAdapter(); + void start() final; +}; + +} // namespace Utils + +QTC_DECLARE_CUSTOM_TASK(ProcessTask, Utils::ProcessTaskAdapter); diff --git a/src/libs/utils/processinfo.cpp b/src/libs/utils/processinfo.cpp index dc41a8f63e..0d71e380fb 100644 --- a/src/libs/utils/processinfo.cpp +++ b/src/libs/utils/processinfo.cpp @@ -4,7 +4,7 @@ #include "processinfo.h" #include "algorithm.h" -#include "qtcprocess.h" +#include "process.h" #include #include diff --git a/src/libs/utils/qtcprocess.cpp b/src/libs/utils/qtcprocess.cpp deleted file mode 100644 index 1fe97b3d2f..0000000000 --- a/src/libs/utils/qtcprocess.cpp +++ /dev/null @@ -1,2163 +0,0 @@ -// Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -#include "qtcprocess.h" - -#include "algorithm.h" -#include "environment.h" -#include "guard.h" -#include "hostosinfo.h" -#include "launcherinterface.h" -#include "launchersocket.h" -#include "processreaper.h" -#include "processutils.h" -#include "stringutils.h" -#include "terminalhooks.h" -#include "threadutils.h" -#include "utilstr.h" - -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef QT_GUI_LIB -// qmlpuppet does not use that. -#include -#include -#endif - -#include -#include -#include -#include -#include -#include -#include - -using namespace Utils::Internal; - -namespace Utils { -namespace Internal { - -const char QTC_PROCESS_BLOCKING_TYPE[] = "__BLOCKING_TYPE__"; -const char QTC_PROCESS_NUMBER[] = "__NUMBER__"; -const char QTC_PROCESS_STARTTIME[] = "__STARTTIME__"; - -class MeasureAndRun -{ -public: - MeasureAndRun(const char *functionName) - : m_functionName(functionName) - , m_measureProcess(qtcEnvironmentVariableIsSet("QTC_MEASURE_PROCESS")) - {} - template - std::invoke_result_t measureAndRun(Function &&function, Args&&... args) - { - if (!m_measureProcess) - return std::invoke(std::forward(function), std::forward(args)...); - QElapsedTimer timer; - timer.start(); - auto cleanup = qScopeGuard([this, &timer] { - const qint64 currentNsecs = timer.nsecsElapsed(); - const bool mainThread = isMainThread(); - const int hitThisAll = m_hitThisAll.fetch_add(1) + 1; - const int hitAllAll = m_hitAllAll.fetch_add(1) + 1; - const int hitThisMain = mainThread - ? m_hitThisMain.fetch_add(1) + 1 - : m_hitThisMain.load(); - const int hitAllMain = mainThread - ? m_hitAllMain.fetch_add(1) + 1 - : m_hitAllMain.load(); - const qint64 totalThisAll = toMs(m_totalThisAll.fetch_add(currentNsecs) + currentNsecs); - const qint64 totalAllAll = toMs(m_totalAllAll.fetch_add(currentNsecs) + currentNsecs); - const qint64 totalThisMain = toMs(mainThread - ? m_totalThisMain.fetch_add(currentNsecs) + currentNsecs - : m_totalThisMain.load()); - const qint64 totalAllMain = toMs(mainThread - ? m_totalAllMain.fetch_add(currentNsecs) + currentNsecs - : m_totalAllMain.load()); - printMeasurement(QLatin1String(m_functionName), hitThisAll, toMs(currentNsecs), - totalThisAll, hitAllAll, totalAllAll, mainThread, - hitThisMain, totalThisMain, hitAllMain, totalAllMain); - }); - return std::invoke(std::forward(function), std::forward(args)...); - } -private: - static void printHeader() - { - // [function/thread]: function:(T)his|(A)ll, thread:(M)ain|(A)ll - qDebug() << "+----------------+-------+---------+----------+-------+----------+---------+-------+----------+-------+----------+"; - qDebug() << "| [Function/Thread] = [(T|A)/(M|A)], where: (T)his function, (A)ll functions / threads, (M)ain thread |"; - qDebug() << "+----------------+-------+---------+----------+-------+----------+---------+-------+----------+-------+----------+"; - qDebug() << "| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 |"; - qDebug() << "| | [T/A] | [T/A] | [T/A] | [A/A] | [A/A] | | [T/M] | [T/M] | [A/M] | [A/M] |"; - qDebug() << "| Function | Hit | Current | Total | Hit | Total | Current | Hit | Total | Hit | Total |"; - qDebug() << "| Name | Count | Measu- | Measu- | Count | Measu- | is Main | Count | Measu- | Count | Measu- |"; - qDebug() << "| | | rement | rement | | rement | Thread | | rement | | rement |"; - qDebug() << "+----------------+-------+---------+----------+-------+----------+---------+-------+----------+-------+----------+"; - } - static void printMeasurement(const QString &functionName, int hitThisAll, int currentNsecs, - int totalThisAll, int hitAllAll, int totalAllAll, bool isMainThread, - int hitThisMain, int totalThisMain, int hitAllMain, int totalAllMain) - { - static const int repeatHeaderLineCount = 25; - if (s_lineCounter.fetch_add(1) % repeatHeaderLineCount == 0) - printHeader(); - - const QString &functionNameField = QString("%1").arg(functionName, 14); - const QString &hitThisAllField = formatField(hitThisAll, 5); - const QString ¤tNsecsField = formatField(currentNsecs, 7, " ms"); - const QString &totalThisAllField = formatField(totalThisAll, 8, " ms"); - const QString &hitAllAllField = formatField(hitAllAll, 5); - const QString &totalAllAllField = formatField(totalAllAll, 8, " ms"); - const QString &mainThreadField = isMainThread ? QString("%1").arg("yes", 7) - : QString("%1").arg("no", 7); - const QString &hitThisMainField = formatField(hitThisMain, 5); - const QString &totalThisMainField = formatField(totalThisMain, 8, " ms"); - const QString &hitAllMainField = formatField(hitAllMain, 5); - const QString &totalAllMainField = formatField(totalAllMain, 8, " ms"); - - const QString &totalString = QString("| %1 | %2 | %3 | %4 | %5 | %6 | %7 | %8 | %9 | %10 | %11 |") - .arg(functionNameField, hitThisAllField, currentNsecsField, - totalThisAllField, hitAllAllField, totalAllAllField, mainThreadField, - hitThisMainField, totalThisMainField, hitAllMainField, totalAllMainField); - qDebug("%s", qPrintable(totalString)); - } - static QString formatField(int number, int fieldWidth, const QString &suffix = {}) - { - return QString("%1%2").arg(number, fieldWidth - suffix.count()).arg(suffix); - } - - static int toMs(quint64 nsesc) // nanoseconds to miliseconds - { - static const int halfMillion = 500000; - static const int million = 2 * halfMillion; - return int((nsesc + halfMillion) / million); - } - - const char * const m_functionName; - const bool m_measureProcess; - std::atomic_int m_hitThisAll = 0; - std::atomic_int m_hitThisMain = 0; - std::atomic_int64_t m_totalThisAll = 0; - std::atomic_int64_t m_totalThisMain = 0; - static std::atomic_int m_hitAllAll; - static std::atomic_int m_hitAllMain; - static std::atomic_int64_t m_totalAllAll; - static std::atomic_int64_t m_totalAllMain; - static std::atomic_int s_lineCounter; -}; - -std::atomic_int MeasureAndRun::m_hitAllAll = 0; -std::atomic_int MeasureAndRun::m_hitAllMain = 0; -std::atomic_int64_t MeasureAndRun::m_totalAllAll = 0; -std::atomic_int64_t MeasureAndRun::m_totalAllMain = 0; -std::atomic_int MeasureAndRun::s_lineCounter = 0; - -static MeasureAndRun s_start = MeasureAndRun("start"); -static MeasureAndRun s_waitForStarted = MeasureAndRun("waitForStarted"); - -enum { debug = 0 }; -enum { syncDebug = 0 }; - -enum { defaultMaxHangTimerCount = 10 }; - -static Q_LOGGING_CATEGORY(processLog, "qtc.utils.qtcprocess", QtWarningMsg) -static Q_LOGGING_CATEGORY(processStdoutLog, "qtc.utils.qtcprocess.stdout", QtWarningMsg) -static Q_LOGGING_CATEGORY(processStderrLog, "qtc.utils.qtcprocess.stderr", QtWarningMsg) - -static DeviceProcessHooks s_deviceHooks; - -// Data for one channel buffer (stderr/stdout) -class ChannelBuffer -{ -public: - void clearForRun(); - - void handleRest(); - void append(const QByteArray &text); - - QByteArray readAllData() { return std::exchange(rawData, {}); } - - QByteArray rawData; - QString incompleteLineBuffer; // lines not yet signaled - QTextCodec *codec = nullptr; // Not owner - std::unique_ptr codecState; - std::function outputCallback; - TextChannelMode m_textChannelMode = TextChannelMode::Off; - - bool emitSingleLines = true; - bool keepRawData = true; -}; - -class DefaultImpl : public ProcessInterface -{ -private: - virtual void start() final; - virtual void doDefaultStart(const QString &program, const QStringList &arguments) = 0; - bool dissolveCommand(QString *program, QStringList *arguments); - bool ensureProgramExists(const QString &program); -}; - -void DefaultImpl::start() -{ - QString program; - QStringList arguments; - if (!dissolveCommand(&program, &arguments)) - return; - if (!ensureProgramExists(program)) - return; - s_start.measureAndRun(&DefaultImpl::doDefaultStart, this, program, arguments); -} - -bool DefaultImpl::dissolveCommand(QString *program, QStringList *arguments) -{ - const CommandLine &commandLine = m_setup.m_commandLine; - QString commandString; - ProcessArgs processArgs; - const bool success = ProcessArgs::prepareCommand(commandLine, &commandString, &processArgs, - &m_setup.m_environment, - &m_setup.m_workingDirectory); - - if (commandLine.executable().osType() == OsTypeWindows) { - QString args; - if (m_setup.m_useCtrlCStub) { - if (m_setup.m_lowPriority) - ProcessArgs::addArg(&args, "-nice"); - ProcessArgs::addArg(&args, QDir::toNativeSeparators(commandString)); - commandString = QCoreApplication::applicationDirPath() - + QLatin1String("/qtcreator_ctrlc_stub.exe"); - } else if (m_setup.m_lowPriority) { - m_setup.m_belowNormalPriority = true; - } - ProcessArgs::addArgs(&args, processArgs.toWindowsArgs()); - m_setup.m_nativeArguments = args; - // Note: Arguments set with setNativeArgs will be appended to the ones - // passed with start() below. - *arguments = {}; - } else { - if (!success) { - const ProcessResultData result = {0, - QProcess::NormalExit, - QProcess::FailedToStart, - Tr::tr("Error in command line.")}; - emit done(result); - return false; - } - *arguments = processArgs.toUnixArgs(); - } - *program = commandString; - return true; -} - -static FilePath resolve(const FilePath &workingDir, const FilePath &filePath) -{ - if (filePath.isAbsolutePath()) - return filePath; - - const FilePath fromWorkingDir = workingDir.resolvePath(filePath); - if (fromWorkingDir.exists() && fromWorkingDir.isExecutableFile()) - return fromWorkingDir; - return filePath.searchInPath(); -} - -bool DefaultImpl::ensureProgramExists(const QString &program) -{ - const FilePath programFilePath = resolve(m_setup.m_workingDirectory, - FilePath::fromString(program)); - if (programFilePath.exists() && programFilePath.isExecutableFile()) - return true; - - const QString errorString - = Tr::tr("The program \"%1\" does not exist or is not executable.").arg(program); - const ProcessResultData result = { 0, QProcess::NormalExit, QProcess::FailedToStart, - errorString }; - emit done(result); - return false; -} - -class QProcessBlockingImpl : public ProcessBlockingInterface -{ -public: - QProcessBlockingImpl(QProcess *process) : m_process(process) {} - -private: - bool waitForSignal(ProcessSignalType signalType, int msecs) final - { - switch (signalType) { - case ProcessSignalType::Started: - return m_process->waitForStarted(msecs); - case ProcessSignalType::ReadyRead: - return m_process->waitForReadyRead(msecs); - case ProcessSignalType::Done: - return m_process->waitForFinished(msecs); - } - return false; - } - - QProcess *m_process = nullptr; -}; - -class PtyProcessImpl final : public DefaultImpl -{ -public: - ~PtyProcessImpl() { QTC_CHECK(m_setup.m_ptyData); m_setup.m_ptyData->setResizeHandler({}); } - - qint64 write(const QByteArray &data) final - { - if (m_ptyProcess) - return m_ptyProcess->write(data); - return -1; - } - - void sendControlSignal(ControlSignal controlSignal) final - { - if (!m_ptyProcess) - return; - - switch (controlSignal) { - case ControlSignal::Terminate: - m_ptyProcess.reset(); - break; - case ControlSignal::Kill: - m_ptyProcess->kill(); - break; - default: - QTC_CHECK(false); - } - } - - void doDefaultStart(const QString &program, const QStringList &arguments) final - { - QTC_CHECK(m_setup.m_ptyData); - m_setup.m_ptyData->setResizeHandler([this](const QSize &size) { - if (m_ptyProcess) - m_ptyProcess->resize(size.width(), size.height()); - }); - m_ptyProcess.reset(PtyQt::createPtyProcess(IPtyProcess::AutoPty)); - if (!m_ptyProcess) { - const ProcessResultData result = {-1, - QProcess::CrashExit, - QProcess::FailedToStart, - "Failed to create pty process"}; - emit done(result); - return; - } - - QProcessEnvironment penv = m_setup.m_environment.toProcessEnvironment(); - if (penv.isEmpty()) - penv = Environment::systemEnvironment().toProcessEnvironment(); - const QStringList senv = penv.toStringList(); - - bool startResult - = m_ptyProcess->startProcess(program, - HostOsInfo::isWindowsHost() - ? QStringList{m_setup.m_nativeArguments} << arguments - : arguments, - m_setup.m_workingDirectory.nativePath(), - senv, - m_setup.m_ptyData->size().width(), - m_setup.m_ptyData->size().height()); - - if (!startResult) { - const ProcessResultData result = {-1, - QProcess::CrashExit, - QProcess::FailedToStart, - "Failed to start pty process: " - + m_ptyProcess->lastError()}; - emit done(result); - return; - } - - if (!m_ptyProcess->lastError().isEmpty()) { - const ProcessResultData result - = {-1, QProcess::CrashExit, QProcess::FailedToStart, m_ptyProcess->lastError()}; - emit done(result); - return; - } - - connect(m_ptyProcess->notifier(), &QIODevice::readyRead, this, [this] { - emit readyRead(m_ptyProcess->readAll(), {}); - }); - - connect(m_ptyProcess->notifier(), &QIODevice::aboutToClose, this, [this] { - if (m_ptyProcess) { - const ProcessResultData result - = {m_ptyProcess->exitCode(), QProcess::NormalExit, QProcess::UnknownError, {}}; - emit done(result); - return; - } - - const ProcessResultData result = {0, QProcess::NormalExit, QProcess::UnknownError, {}}; - emit done(result); - }); - - emit started(m_ptyProcess->pid()); - } - -private: - std::unique_ptr m_ptyProcess; -}; - -class QProcessImpl final : public DefaultImpl -{ -public: - QProcessImpl() - : m_process(new ProcessHelper(this)) - , m_blockingImpl(new QProcessBlockingImpl(m_process)) - { - connect(m_process, &QProcess::started, this, &QProcessImpl::handleStarted); - connect(m_process, &QProcess::finished, this, &QProcessImpl::handleFinished); - connect(m_process, &QProcess::errorOccurred, this, &QProcessImpl::handleError); - connect(m_process, &QProcess::readyReadStandardOutput, this, [this] { - emit readyRead(m_process->readAllStandardOutput(), {}); - }); - connect(m_process, &QProcess::readyReadStandardError, this, [this] { - emit readyRead({}, m_process->readAllStandardError()); - }); - } - ~QProcessImpl() final { ProcessReaper::reap(m_process, m_setup.m_reaperTimeout); } - -private: - qint64 write(const QByteArray &data) final { return m_process->write(data); } - void sendControlSignal(ControlSignal controlSignal) final { - switch (controlSignal) { - case ControlSignal::Terminate: - ProcessHelper::terminateProcess(m_process); - break; - case ControlSignal::Kill: - m_process->kill(); - break; - case ControlSignal::Interrupt: - ProcessHelper::interruptProcess(m_process); - break; - case ControlSignal::KickOff: - QTC_CHECK(false); - break; - case ControlSignal::CloseWriteChannel: - m_process->closeWriteChannel(); - break; - } - } - - virtual ProcessBlockingInterface *processBlockingInterface() const { return m_blockingImpl; } - - void doDefaultStart(const QString &program, const QStringList &arguments) final - { - QTC_ASSERT(QThread::currentThread()->eventDispatcher(), - qWarning("QtcProcess::start(): Starting a process in a non QThread thread " - "may cause infinite hang when destroying the running process.")); - ProcessStartHandler *handler = m_process->processStartHandler(); - handler->setProcessMode(m_setup.m_processMode); - handler->setWriteData(m_setup.m_writeData); - handler->setNativeArguments(m_setup.m_nativeArguments); - handler->setWindowsSpecificStartupFlags(m_setup.m_belowNormalPriority, - m_setup.m_createConsoleOnWindows); - - const QProcessEnvironment penv = m_setup.m_environment.toProcessEnvironment(); - if (!penv.isEmpty()) - m_process->setProcessEnvironment(penv); - m_process->setWorkingDirectory(m_setup.m_workingDirectory.path()); - m_process->setStandardInputFile(m_setup.m_standardInputFile); - m_process->setProcessChannelMode(m_setup.m_processChannelMode); - if (m_setup.m_lowPriority) - m_process->setLowPriority(); - if (m_setup.m_unixTerminalDisabled) - m_process->setUnixTerminalDisabled(); - m_process->setUseCtrlCStub(m_setup.m_useCtrlCStub); - m_process->start(program, arguments, handler->openMode()); - handler->handleProcessStart(); - } - - void handleStarted() - { - m_process->processStartHandler()->handleProcessStarted(); - emit started(m_process->processId()); - } - - void handleError(QProcess::ProcessError error) - { - if (error != QProcess::FailedToStart) - return; - const ProcessResultData result = { m_process->exitCode(), m_process->exitStatus(), - error, m_process->errorString() }; - emit done(result); - } - - void handleFinished(int exitCode, QProcess::ExitStatus exitStatus) - { - const ProcessResultData result = { exitCode, exitStatus, - m_process->error(), m_process->errorString() }; - emit done(result); - } - - ProcessHelper *m_process = nullptr; - QProcessBlockingImpl *m_blockingImpl = nullptr; -}; - -static uint uniqueToken() -{ - static std::atomic_uint globalUniqueToken = 0; - return ++globalUniqueToken; -} - -class ProcessLauncherBlockingImpl : public ProcessBlockingInterface -{ -public: - ProcessLauncherBlockingImpl(CallerHandle *caller) : m_caller(caller) {} - -private: - bool waitForSignal(ProcessSignalType signalType, int msecs) final - { - // TODO: Remove CallerHandle::SignalType - const CallerHandle::SignalType type = [signalType] { - switch (signalType) { - case ProcessSignalType::Started: - return CallerHandle::SignalType::Started; - case ProcessSignalType::ReadyRead: - return CallerHandle::SignalType::ReadyRead; - case ProcessSignalType::Done: - return CallerHandle::SignalType::Done; - } - QTC_CHECK(false); - return CallerHandle::SignalType::NoSignal; - }(); - return m_caller->waitForSignal(type, msecs); - } - - CallerHandle *m_caller = nullptr; -}; - -class ProcessLauncherImpl final : public DefaultImpl -{ - Q_OBJECT -public: - ProcessLauncherImpl() : m_token(uniqueToken()) - { - m_handle = LauncherInterface::registerHandle(this, token()); - m_handle->setProcessSetupData(&m_setup); - connect(m_handle, &CallerHandle::started, - this, &ProcessInterface::started); - connect(m_handle, &CallerHandle::readyRead, - this, &ProcessInterface::readyRead); - connect(m_handle, &CallerHandle::done, - this, &ProcessInterface::done); - m_blockingImpl = new ProcessLauncherBlockingImpl(m_handle); - } - ~ProcessLauncherImpl() final - { - m_handle->close(); - LauncherInterface::unregisterHandle(token()); - m_handle = nullptr; - } - -private: - qint64 write(const QByteArray &data) final { return m_handle->write(data); } - void sendControlSignal(ControlSignal controlSignal) final { - switch (controlSignal) { - case ControlSignal::Terminate: - m_handle->terminate(); - break; - case ControlSignal::Kill: - m_handle->kill(); - break; - case ControlSignal::Interrupt: - ProcessHelper::interruptPid(m_handle->processId()); - break; - case ControlSignal::KickOff: - QTC_CHECK(false); - break; - case ControlSignal::CloseWriteChannel: - m_handle->closeWriteChannel(); - break; - } - } - - virtual ProcessBlockingInterface *processBlockingInterface() const { return m_blockingImpl; } - - void doDefaultStart(const QString &program, const QStringList &arguments) final - { - m_handle->start(program, arguments); - } - - quintptr token() const { return m_token; } - - const uint m_token = 0; - // Lives in caller's thread. - CallerHandle *m_handle = nullptr; - ProcessLauncherBlockingImpl *m_blockingImpl = nullptr; -}; - -static ProcessImpl defaultProcessImpl() -{ - if (qtcEnvironmentVariableIsSet("QTC_USE_QPROCESS")) - return ProcessImpl::QProcess; - return ProcessImpl::ProcessLauncher; -} - -class ProcessInterfaceSignal -{ -public: - ProcessSignalType signalType() const { return m_signalType; } - virtual ~ProcessInterfaceSignal() = default; -protected: - ProcessInterfaceSignal(ProcessSignalType signalType) : m_signalType(signalType) {} -private: - const ProcessSignalType m_signalType; -}; - -class StartedSignal : public ProcessInterfaceSignal -{ -public: - StartedSignal(qint64 processId, qint64 applicationMainThreadId) - : ProcessInterfaceSignal(ProcessSignalType::Started) - , m_processId(processId) - , m_applicationMainThreadId(applicationMainThreadId) {} - qint64 processId() const { return m_processId; } - qint64 applicationMainThreadId() const { return m_applicationMainThreadId; } -private: - const qint64 m_processId; - const qint64 m_applicationMainThreadId; -}; - -class ReadyReadSignal : public ProcessInterfaceSignal -{ -public: - ReadyReadSignal(const QByteArray &stdOut, const QByteArray &stdErr) - : ProcessInterfaceSignal(ProcessSignalType::ReadyRead) - , m_stdOut(stdOut) - , m_stdErr(stdErr) {} - QByteArray stdOut() const { return m_stdOut; } - QByteArray stdErr() const { return m_stdErr; } -private: - const QByteArray m_stdOut; - const QByteArray m_stdErr; -}; - -class DoneSignal : public ProcessInterfaceSignal -{ -public: - DoneSignal(const ProcessResultData &resultData) - : ProcessInterfaceSignal(ProcessSignalType::Done) - , m_resultData(resultData) {} - ProcessResultData resultData() const { return m_resultData; } -private: - const ProcessResultData m_resultData; -}; - -class GeneralProcessBlockingImpl; - -class ProcessInterfaceHandler : public QObject -{ -public: - ProcessInterfaceHandler(GeneralProcessBlockingImpl *caller, ProcessInterface *process); - - // Called from caller's thread exclusively. - bool waitForSignal(ProcessSignalType newSignal, int msecs); - void moveToCallerThread(); - -private: - // Called from caller's thread exclusively. - bool doWaitForSignal(QDeadlineTimer deadline); - - // Called from caller's thread when not waiting for signal, - // otherwise called from temporary thread. - void handleStarted(qint64 processId, qint64 applicationMainThreadId); - void handleReadyRead(const QByteArray &outputData, const QByteArray &errorData); - void handleDone(const ProcessResultData &data); - void appendSignal(ProcessInterfaceSignal *newSignal); - - GeneralProcessBlockingImpl *m_caller = nullptr; - QMutex m_mutex; - QWaitCondition m_waitCondition; -}; - -class GeneralProcessBlockingImpl : public ProcessBlockingInterface -{ -public: - GeneralProcessBlockingImpl(QtcProcessPrivate *parent); - - void flush() { flushSignals(takeAllSignals()); } - bool flushFor(ProcessSignalType signalType) { - return flushSignals(takeSignalsFor(signalType), &signalType); - } - - bool shouldFlush() const { QMutexLocker locker(&m_mutex); return !m_signals.isEmpty(); } - // Called from ProcessInterfaceHandler thread exclusively. - void appendSignal(ProcessInterfaceSignal *launcherSignal); - -private: - // Called from caller's thread exclusively - bool waitForSignal(ProcessSignalType newSignal, int msecs) final; - - QList takeAllSignals(); - QList takeSignalsFor(ProcessSignalType signalType); - bool flushSignals(const QList &signalList, - ProcessSignalType *signalType = nullptr); - - void handleStartedSignal(const StartedSignal *launcherSignal); - void handleReadyReadSignal(const ReadyReadSignal *launcherSignal); - void handleDoneSignal(const DoneSignal *launcherSignal); - - QtcProcessPrivate *m_caller = nullptr; - std::unique_ptr m_processHandler; - mutable QMutex m_mutex; - QList m_signals; -}; - -class QtcProcessPrivate : public QObject -{ -public: - explicit QtcProcessPrivate(Process *parent) - : QObject(parent) - , q(parent) - , m_killTimer(this) - { - m_killTimer.setSingleShot(true); - connect(&m_killTimer, &QTimer::timeout, this, [this] { - m_killTimer.stop(); - sendControlSignal(ControlSignal::Kill); - }); - setupDebugLog(); - } - - void setupDebugLog(); - void storeEventLoopDebugInfo(const QVariant &value); - - ProcessInterface *createProcessInterface() - { - if (m_setup.m_ptyData) - return new PtyProcessImpl; - if (m_setup.m_terminalMode != TerminalMode::Off) - return Terminal::Hooks::instance().createTerminalProcessInterface(); - - const ProcessImpl impl = m_setup.m_processImpl == ProcessImpl::Default - ? defaultProcessImpl() : m_setup.m_processImpl; - if (impl == ProcessImpl::QProcess) - return new QProcessImpl; - return new ProcessLauncherImpl; - } - - void setProcessInterface(ProcessInterface *process) - { - if (m_process) - m_process->disconnect(); - m_process.reset(process); - m_process->setParent(this); - connect(m_process.get(), &ProcessInterface::started, - this, &QtcProcessPrivate::handleStarted); - connect(m_process.get(), &ProcessInterface::readyRead, - this, &QtcProcessPrivate::handleReadyRead); - connect(m_process.get(), &ProcessInterface::done, - this, &QtcProcessPrivate::handleDone); - - m_blockingInterface.reset(process->processBlockingInterface()); - if (!m_blockingInterface) - m_blockingInterface.reset(new GeneralProcessBlockingImpl(this)); - m_blockingInterface->setParent(this); - } - - CommandLine fullCommandLine() const - { - if (!m_setup.m_runAsRoot || HostOsInfo::isWindowsHost()) - return m_setup.m_commandLine; - CommandLine rootCommand("sudo", {"-A"}); - rootCommand.addCommandLineAsArgs(m_setup.m_commandLine); - return rootCommand; - } - - Process *q; - std::unique_ptr m_blockingInterface; - std::unique_ptr m_process; - ProcessSetupData m_setup; - - void slotTimeout(); - void handleStarted(qint64 processId, qint64 applicationMainThreadId); - void handleReadyRead(const QByteArray &outputData, const QByteArray &errorData); - void handleDone(const ProcessResultData &data); - void clearForRun(); - - void emitGuardedSignal(void (Process::* signalName)()) { - GuardLocker locker(m_guard); - emit (q->*signalName)(); - } - - ProcessResult interpretExitCode(int exitCode); - - bool waitForSignal(ProcessSignalType signalType, int msecs); - Qt::ConnectionType connectionType() const; - void sendControlSignal(ControlSignal controlSignal); - - QTimer m_killTimer; - QProcess::ProcessState m_state = QProcess::NotRunning; - qint64 m_processId = 0; - qint64 m_applicationMainThreadId = 0; - ProcessResultData m_resultData; - - QTextCodec *m_codec = QTextCodec::codecForLocale(); - QEventLoop *m_eventLoop = nullptr; - ProcessResult m_result = ProcessResult::StartFailed; - ChannelBuffer m_stdOut; - ChannelBuffer m_stdErr; - ExitCodeInterpreter m_exitCodeInterpreter; - - int m_hangTimerCount = 0; - int m_maxHangTimerCount = defaultMaxHangTimerCount; - bool m_timeOutMessageBoxEnabled = false; - bool m_waitingForUser = false; - - Guard m_guard; -}; - -ProcessInterfaceHandler::ProcessInterfaceHandler(GeneralProcessBlockingImpl *caller, - ProcessInterface *process) - : m_caller(caller) -{ - process->disconnect(); - connect(process, &ProcessInterface::started, - this, &ProcessInterfaceHandler::handleStarted); - connect(process, &ProcessInterface::readyRead, - this, &ProcessInterfaceHandler::handleReadyRead); - connect(process, &ProcessInterface::done, - this, &ProcessInterfaceHandler::handleDone); -} - -// Called from caller's thread exclusively. -bool ProcessInterfaceHandler::waitForSignal(ProcessSignalType newSignal, int msecs) -{ - QDeadlineTimer deadline(msecs); - while (true) { - if (deadline.hasExpired()) - break; - if (!doWaitForSignal(deadline)) - break; - // Matching (or Done) signal was flushed - if (m_caller->flushFor(newSignal)) - return true; - // Otherwise continue awaiting (e.g. when ReadyRead came while waitForFinished()) - } - return false; -} - -// Called from caller's thread exclusively. -void ProcessInterfaceHandler::moveToCallerThread() -{ - QMetaObject::invokeMethod(this, [this] { - moveToThread(m_caller->thread()); - }, Qt::BlockingQueuedConnection); -} - -// Called from caller's thread exclusively. -bool ProcessInterfaceHandler::doWaitForSignal(QDeadlineTimer deadline) -{ - QMutexLocker locker(&m_mutex); - - // Flush, if we have any stored signals. - // This must be called when holding laucher's mutex locked prior to the call to wait, - // so that it's done atomically. - if (m_caller->shouldFlush()) - return true; - - return m_waitCondition.wait(&m_mutex, deadline); -} - -// Called from ProcessInterfaceHandler thread exclusively -void ProcessInterfaceHandler::handleStarted(qint64 processId, qint64 applicationMainThreadId) -{ - appendSignal(new StartedSignal(processId, applicationMainThreadId)); -} - -// Called from ProcessInterfaceHandler thread exclusively -void ProcessInterfaceHandler::handleReadyRead(const QByteArray &outputData, const QByteArray &errorData) -{ - appendSignal(new ReadyReadSignal(outputData, errorData)); -} - -// Called from ProcessInterfaceHandler thread exclusively -void ProcessInterfaceHandler::handleDone(const ProcessResultData &data) -{ - appendSignal(new DoneSignal(data)); -} - -void ProcessInterfaceHandler::appendSignal(ProcessInterfaceSignal *newSignal) -{ - { - QMutexLocker locker(&m_mutex); - m_caller->appendSignal(newSignal); - } - m_waitCondition.wakeOne(); - // call in callers thread - QMetaObject::invokeMethod(m_caller, &GeneralProcessBlockingImpl::flush); -} - -GeneralProcessBlockingImpl::GeneralProcessBlockingImpl(QtcProcessPrivate *parent) - : m_caller(parent) - , m_processHandler(new ProcessInterfaceHandler(this, parent->m_process.get())) -{ - // In order to move the process interface into another thread together with handle - parent->m_process.get()->setParent(m_processHandler.get()); - m_processHandler->setParent(this); - // So the hierarchy looks like: - // QtcProcessPrivate - // | - // +- GeneralProcessBlockingImpl - // | - // +- ProcessInterfaceHandler - // | - // +- ProcessInterface -} - -bool GeneralProcessBlockingImpl::waitForSignal(ProcessSignalType newSignal, int msecs) -{ - m_processHandler->setParent(nullptr); - - QThread thread; - thread.start(); - // Note: the thread may have started before and it's appending new signals before - // waitForSignal() is called. However, in this case they won't be flushed since - // the caller here is blocked, so all signals should be buffered and we are going - // to flush them from inside waitForSignal(). - m_processHandler->moveToThread(&thread); - const bool result = m_processHandler->waitForSignal(newSignal, msecs); - m_processHandler->moveToCallerThread(); - m_processHandler->setParent(this); - thread.quit(); - thread.wait(); - return result; -} - -// Called from caller's thread exclusively -QList GeneralProcessBlockingImpl::takeAllSignals() -{ - QMutexLocker locker(&m_mutex); - return std::exchange(m_signals, {}); -} - -// Called from caller's thread exclusively -QList GeneralProcessBlockingImpl::takeSignalsFor(ProcessSignalType signalType) -{ - // If we are flushing for ReadyRead or Done - flush all. - if (signalType != ProcessSignalType::Started) - return takeAllSignals(); - - QMutexLocker locker(&m_mutex); - const QList storedSignals = transform(std::as_const(m_signals), - [](const ProcessInterfaceSignal *aSignal) { - return aSignal->signalType(); - }); - - // If we are flushing for Started: - // - if Started was buffered - flush Started only (even when Done was buffered) - // - otherwise if Done signal was buffered - flush all. - if (!storedSignals.contains(ProcessSignalType::Started) - && storedSignals.contains(ProcessSignalType::Done)) { - return std::exchange(m_signals, {}); // avoid takeAllSignals() because of mutex locked - } - - QList oldSignals; - const auto matchingIndex = storedSignals.lastIndexOf(signalType); - if (matchingIndex >= 0) { - oldSignals = m_signals.mid(0, matchingIndex + 1); - m_signals = m_signals.mid(matchingIndex + 1); - } - return oldSignals; -} - -// Called from caller's thread exclusively -bool GeneralProcessBlockingImpl::flushSignals(const QList &signalList, - ProcessSignalType *signalType) -{ - bool signalMatched = false; - for (const ProcessInterfaceSignal *storedSignal : std::as_const(signalList)) { - const ProcessSignalType storedSignalType = storedSignal->signalType(); - if (signalType && storedSignalType == *signalType) - signalMatched = true; - switch (storedSignalType) { - case ProcessSignalType::Started: - handleStartedSignal(static_cast(storedSignal)); - break; - case ProcessSignalType::ReadyRead: - handleReadyReadSignal(static_cast(storedSignal)); - break; - case ProcessSignalType::Done: - if (signalType) - signalMatched = true; - handleDoneSignal(static_cast(storedSignal)); - break; - } - delete storedSignal; - } - return signalMatched; -} - -void GeneralProcessBlockingImpl::handleStartedSignal(const StartedSignal *aSignal) -{ - m_caller->handleStarted(aSignal->processId(), aSignal->applicationMainThreadId()); -} - -void GeneralProcessBlockingImpl::handleReadyReadSignal(const ReadyReadSignal *aSignal) -{ - m_caller->handleReadyRead(aSignal->stdOut(), aSignal->stdErr()); -} - -void GeneralProcessBlockingImpl::handleDoneSignal(const DoneSignal *aSignal) -{ - m_caller->handleDone(aSignal->resultData()); -} - -// Called from ProcessInterfaceHandler thread exclusively. -void GeneralProcessBlockingImpl::appendSignal(ProcessInterfaceSignal *newSignal) -{ - QMutexLocker locker(&m_mutex); - m_signals.append(newSignal); -} - -bool QtcProcessPrivate::waitForSignal(ProcessSignalType newSignal, int msecs) -{ - const QDeadlineTimer timeout(msecs); - const QDeadlineTimer currentKillTimeout(m_killTimer.remainingTime()); - const bool needsSplit = m_killTimer.isActive() ? timeout > currentKillTimeout : false; - const QDeadlineTimer mainTimeout = needsSplit ? currentKillTimeout : timeout; - - bool result = m_blockingInterface->waitForSignal(newSignal, mainTimeout.remainingTime()); - if (!result && needsSplit) { - m_killTimer.stop(); - sendControlSignal(ControlSignal::Kill); - result = m_blockingInterface->waitForSignal(newSignal, timeout.remainingTime()); - } - return result; -} - -Qt::ConnectionType QtcProcessPrivate::connectionType() const -{ - return (m_process->thread() == thread()) ? Qt::DirectConnection - : Qt::BlockingQueuedConnection; -} - -void QtcProcessPrivate::sendControlSignal(ControlSignal controlSignal) -{ - QTC_ASSERT(QThread::currentThread() == thread(), return); - if (!m_process || (m_state == QProcess::NotRunning)) - return; - - if (controlSignal == ControlSignal::Terminate || controlSignal == ControlSignal::Kill) - m_resultData.m_canceledByUser = true; - - QMetaObject::invokeMethod(m_process.get(), [this, controlSignal] { - m_process->sendControlSignal(controlSignal); - }, connectionType()); -} - -void QtcProcessPrivate::clearForRun() -{ - m_hangTimerCount = 0; - m_stdOut.clearForRun(); - m_stdOut.codec = m_codec; - m_stdErr.clearForRun(); - m_stdErr.codec = m_codec; - m_result = ProcessResult::StartFailed; - - m_killTimer.stop(); - m_state = QProcess::NotRunning; - m_processId = 0; - m_applicationMainThreadId = 0; - m_resultData = {}; -} - -ProcessResult QtcProcessPrivate::interpretExitCode(int exitCode) -{ - if (m_exitCodeInterpreter) - return m_exitCodeInterpreter(exitCode); - - // default: - return exitCode ? ProcessResult::FinishedWithError : ProcessResult::FinishedWithSuccess; -} - -} // Internal - -/*! - \class Utils::QtcProcess - - \brief The QtcProcess class provides functionality for with processes. - - \sa Utils::ProcessArgs -*/ - -Process::Process(QObject *parent) - : QObject(parent), - d(new QtcProcessPrivate(this)) -{ - qRegisterMetaType("ProcessResultData"); - static int qProcessExitStatusMeta = qRegisterMetaType(); - static int qProcessProcessErrorMeta = qRegisterMetaType(); - Q_UNUSED(qProcessExitStatusMeta) - Q_UNUSED(qProcessProcessErrorMeta) -} - -Process::~Process() -{ - QTC_ASSERT(!d->m_guard.isLocked(), qWarning("Deleting QtcProcess instance directly from " - "one of its signal handlers will lead to crash!")); - if (d->m_process) - d->m_process->disconnect(); - delete d; -} - -void Process::setProcessImpl(ProcessImpl processImpl) -{ - d->m_setup.m_processImpl = processImpl; -} - -void Process::setPtyData(const std::optional &data) -{ - d->m_setup.m_ptyData = data; -} - -std::optional Process::ptyData() const -{ - return d->m_setup.m_ptyData; -} - -ProcessMode Process::processMode() const -{ - return d->m_setup.m_processMode; -} - -void Process::setTerminalMode(TerminalMode mode) -{ - d->m_setup.m_terminalMode = mode; -} - -TerminalMode Process::terminalMode() const -{ - return d->m_setup.m_terminalMode; -} - -void Process::setProcessMode(ProcessMode processMode) -{ - d->m_setup.m_processMode = processMode; -} - -void Process::setEnvironment(const Environment &env) -{ - d->m_setup.m_environment = env; -} - -const Environment &Process::environment() const -{ - return d->m_setup.m_environment; -} - -void Process::setControlEnvironment(const Environment &environment) -{ - d->m_setup.m_controlEnvironment = environment; -} - -const Environment &Process::controlEnvironment() const -{ - return d->m_setup.m_controlEnvironment; -} - -void Process::setCommand(const CommandLine &cmdLine) -{ - if (d->m_setup.m_workingDirectory.needsDevice() && cmdLine.executable().needsDevice()) { - QTC_CHECK(d->m_setup.m_workingDirectory.host() == cmdLine.executable().host()); - } - d->m_setup.m_commandLine = cmdLine; -} - -const CommandLine &Process::commandLine() const -{ - return d->m_setup.m_commandLine; -} - -FilePath Process::workingDirectory() const -{ - return d->m_setup.m_workingDirectory; -} - -void Process::setWorkingDirectory(const FilePath &dir) -{ - if (dir.needsDevice() && d->m_setup.m_commandLine.executable().needsDevice()) { - QTC_CHECK(dir.host() == d->m_setup.m_commandLine.executable().host()); - } - d->m_setup.m_workingDirectory = dir; -} - -void Process::setUseCtrlCStub(bool enabled) -{ - d->m_setup.m_useCtrlCStub = enabled; -} - -void Process::start() -{ - QTC_ASSERT(state() == QProcess::NotRunning, return); - QTC_ASSERT(!(d->m_process && d->m_guard.isLocked()), - qWarning("Restarting the QtcProcess directly from one of its signal handlers will " - "lead to crash! Consider calling close() prior to direct restart.")); - d->clearForRun(); - ProcessInterface *processImpl = nullptr; - if (d->m_setup.m_commandLine.executable().needsDevice()) { - QTC_ASSERT(s_deviceHooks.processImplHook, return); - processImpl = s_deviceHooks.processImplHook(commandLine().executable()); - } else { - processImpl = d->createProcessInterface(); - } - QTC_ASSERT(processImpl, return); - d->setProcessInterface(processImpl); - d->m_state = QProcess::Starting; - d->m_process->m_setup = d->m_setup; - d->m_process->m_setup.m_commandLine = d->fullCommandLine(); - d->emitGuardedSignal(&Process::starting); - d->m_process->start(); -} - -void Process::terminate() -{ - d->sendControlSignal(ControlSignal::Terminate); -} - -void Process::kill() -{ - d->sendControlSignal(ControlSignal::Kill); -} - -void Process::interrupt() -{ - d->sendControlSignal(ControlSignal::Interrupt); -} - -void Process::kickoffProcess() -{ - d->sendControlSignal(ControlSignal::KickOff); -} - -void Process::closeWriteChannel() -{ - d->sendControlSignal(ControlSignal::CloseWriteChannel); -} - -bool Process::startDetached(const CommandLine &cmd, const FilePath &workingDirectory, qint64 *pid) -{ - return QProcess::startDetached(cmd.executable().toUserOutput(), - cmd.splitArguments(), - workingDirectory.toUserOutput(), - pid); -} - -void Process::setLowPriority() -{ - d->m_setup.m_lowPriority = true; -} - -void Process::setDisableUnixTerminal() -{ - d->m_setup.m_unixTerminalDisabled = true; -} - -void Process::setAbortOnMetaChars(bool abort) -{ - d->m_setup.m_abortOnMetaChars = abort; -} - -void Process::setRunAsRoot(bool on) -{ - d->m_setup.m_runAsRoot = on; -} - -bool Process::isRunAsRoot() const -{ - return d->m_setup.m_runAsRoot; -} - -void Process::setStandardInputFile(const QString &inputFile) -{ - d->m_setup.m_standardInputFile = inputFile; -} - -QString Process::toStandaloneCommandLine() const -{ - QStringList parts; - parts.append("/usr/bin/env"); - if (!d->m_setup.m_workingDirectory.isEmpty()) { - parts.append("-C"); - d->m_setup.m_workingDirectory.path(); - } - parts.append("-i"); - if (d->m_setup.m_environment.hasChanges()) { - const QStringList envVars = d->m_setup.m_environment.toStringList(); - std::transform(envVars.cbegin(), envVars.cend(), - std::back_inserter(parts), ProcessArgs::quoteArgUnix); - } - parts.append(d->m_setup.m_commandLine.executable().path()); - parts.append(d->m_setup.m_commandLine.splitArguments()); - return parts.join(" "); -} - -void Process::setCreateConsoleOnWindows(bool create) -{ - d->m_setup.m_createConsoleOnWindows = create; -} - -bool Process::createConsoleOnWindows() const -{ - return d->m_setup.m_createConsoleOnWindows; -} - -void Process::setExtraData(const QString &key, const QVariant &value) -{ - d->m_setup.m_extraData.insert(key, value); -} - -QVariant Process::extraData(const QString &key) const -{ - return d->m_setup.m_extraData.value(key); -} - -void Process::setExtraData(const QVariantHash &extraData) -{ - d->m_setup.m_extraData = extraData; -} - -QVariantHash Process::extraData() const -{ - return d->m_setup.m_extraData; -} - -void Process::setReaperTimeout(int msecs) -{ - d->m_setup.m_reaperTimeout = msecs; -} - -int Process::reaperTimeout() const -{ - return d->m_setup.m_reaperTimeout; -} - -void Process::setRemoteProcessHooks(const DeviceProcessHooks &hooks) -{ - s_deviceHooks = hooks; -} - -static bool askToKill(const CommandLine &command) -{ -#ifdef QT_GUI_LIB - if (!isMainThread()) - return true; - const QString title = Tr::tr("Process Not Responding"); - QString msg = command.isEmpty() ? Tr::tr("The process is not responding.") - : Tr::tr("The process \"%1\" is not responding.") - .arg(command.executable().toUserOutput()); - msg += ' '; - msg += Tr::tr("Terminate the process?"); - // Restore the cursor that is set to wait while running. - const bool hasOverrideCursor = QApplication::overrideCursor() != nullptr; - if (hasOverrideCursor) - QApplication::restoreOverrideCursor(); - QMessageBox::StandardButton answer = QMessageBox::question(nullptr, title, msg, QMessageBox::Yes|QMessageBox::No); - if (hasOverrideCursor) - QApplication::setOverrideCursor(Qt::WaitCursor); - return answer == QMessageBox::Yes; -#else - Q_UNUSED(command) - return true; -#endif -} - -// Helper for running a process synchronously in the foreground with timeout -// detection (taking effect after no more output -// occurs on stderr/stdout as opposed to waitForFinished()). Returns false if a timeout -// occurs. Checking of the process' exit state/code still has to be done. - -bool Process::readDataFromProcess(QByteArray *stdOut, QByteArray *stdErr, int timeoutS) -{ - enum { syncDebug = 0 }; - if (syncDebug) - qDebug() << ">readDataFromProcess" << timeoutS; - if (state() != QProcess::Running) { - qWarning("readDataFromProcess: Process in non-running state passed in."); - return false; - } - - // Keep the process running until it has no longer has data - bool finished = false; - bool hasData = false; - do { - finished = waitForFinished(timeoutS > 0 ? timeoutS * 1000 : -1) - || state() == QProcess::NotRunning; - // First check 'stdout' - const QByteArray newStdOut = readAllRawStandardOutput(); - if (!newStdOut.isEmpty()) { - hasData = true; - if (stdOut) - stdOut->append(newStdOut); - } - // Check 'stderr' separately. This is a special handling - // for 'git pull' and the like which prints its progress on stderr. - const QByteArray newStdErr = readAllRawStandardError(); - if (!newStdErr.isEmpty()) { - hasData = true; - if (stdErr) - stdErr->append(newStdErr); - } - // Prompt user, pretend we have data if says 'No'. - const bool hang = !hasData && !finished; - hasData = hang && !askToKill(d->m_setup.m_commandLine); - } while (hasData && !finished); - if (syncDebug) - qDebug() << "m_result; -} - -ProcessResultData Process::resultData() const -{ - return d->m_resultData; -} - -int Process::exitCode() const -{ - return resultData().m_exitCode; -} - -QProcess::ExitStatus Process::exitStatus() const -{ - return resultData().m_exitStatus; -} - -QProcess::ProcessError Process::error() const -{ - return resultData().m_error; -} - -QString Process::errorString() const -{ - return resultData().m_errorString; -} - -// Path utilities - -Environment Process::systemEnvironmentForBinary(const FilePath &filePath) -{ - if (filePath.needsDevice()) { - QTC_ASSERT(s_deviceHooks.systemEnvironmentForBinary, return {}); - return s_deviceHooks.systemEnvironmentForBinary(filePath); - } - - return Environment::systemEnvironment(); -} - -qint64 Process::applicationMainThreadId() const -{ - return d->m_applicationMainThreadId; -} - -QProcess::ProcessChannelMode Process::processChannelMode() const -{ - return d->m_setup.m_processChannelMode; -} - -void Process::setProcessChannelMode(QProcess::ProcessChannelMode mode) -{ - d->m_setup.m_processChannelMode = mode; -} - -QProcess::ProcessState Process::state() const -{ - return d->m_state; -} - -bool Process::isRunning() const -{ - return state() == QProcess::Running; -} - -qint64 Process::processId() const -{ - return d->m_processId; -} - -bool Process::waitForStarted(int msecs) -{ - QTC_ASSERT(d->m_process, return false); - if (d->m_state == QProcess::Running) - return true; - if (d->m_state == QProcess::NotRunning) - return false; - return s_waitForStarted.measureAndRun(&QtcProcessPrivate::waitForSignal, d, - ProcessSignalType::Started, msecs); -} - -bool Process::waitForReadyRead(int msecs) -{ - QTC_ASSERT(d->m_process, return false); - if (d->m_state == QProcess::NotRunning) - return false; - return d->waitForSignal(ProcessSignalType::ReadyRead, msecs); -} - -bool Process::waitForFinished(int msecs) -{ - QTC_ASSERT(d->m_process, return false); - if (d->m_state == QProcess::NotRunning) - return false; - return d->waitForSignal(ProcessSignalType::Done, msecs); -} - -QByteArray Process::readAllRawStandardOutput() -{ - return d->m_stdOut.readAllData(); -} - -QByteArray Process::readAllRawStandardError() -{ - return d->m_stdErr.readAllData(); -} - -qint64 Process::write(const QString &input) -{ - // Non-windows is assumed to be UTF-8 - if (commandLine().executable().osType() != OsTypeWindows) - return writeRaw(input.toUtf8()); - - if (HostOsInfo::hostOs() == OsTypeWindows) - return writeRaw(input.toLocal8Bit()); - - // "remote" Windows target on non-Windows host is unlikely, - // but the true encoding is not accessible. Use UTF8 as best guess. - QTC_CHECK(false); - return writeRaw(input.toUtf8()); -} - -qint64 Process::writeRaw(const QByteArray &input) -{ - QTC_ASSERT(processMode() == ProcessMode::Writer, return -1); - QTC_ASSERT(d->m_process, return -1); - QTC_ASSERT(state() == QProcess::Running, return -1); - QTC_ASSERT(QThread::currentThread() == thread(), return -1); - qint64 result = -1; - QMetaObject::invokeMethod(d->m_process.get(), [this, input] { - d->m_process->write(input); - }, d->connectionType(), &result); - return result; -} - -void Process::close() -{ - QTC_ASSERT(QThread::currentThread() == thread(), return); - if (d->m_process) { - // Note: the m_process may be inside ProcessInterfaceHandler's thread. - QTC_ASSERT(d->m_process->thread() == thread(), return); - d->m_process->disconnect(); - d->m_process.release()->deleteLater(); - } - if (d->m_blockingInterface) { - d->m_blockingInterface->disconnect(); - d->m_blockingInterface.release()->deleteLater(); - } - d->clearForRun(); -} - -/* - Calls terminate() directly and after a delay of reaperTimeout() it calls kill() - if the process is still running. -*/ -void Process::stop() -{ - if (state() == QProcess::NotRunning) - return; - - d->sendControlSignal(ControlSignal::Terminate); - d->m_killTimer.start(d->m_process->m_setup.m_reaperTimeout); -} - -QString Process::readAllStandardOutput() -{ - return QString::fromUtf8(readAllRawStandardOutput()); -} - -QString Process::readAllStandardError() -{ - return QString::fromUtf8(readAllRawStandardError()); -} - -/*! - \class Utils::SynchronousProcess - - \brief The SynchronousProcess class runs a synchronous process in its own - event loop that blocks only user input events. Thus, it allows for the GUI to - repaint and append output to log windows. - - The callbacks set with setStdOutCallback(), setStdErrCallback() are called - with complete lines based on the '\\n' marker. - They would typically be used for log windows. - - Alternatively you can used setStdOutLineCallback() and setStdErrLineCallback() - to process the output line by line. - - There is a timeout handling that takes effect after the last data have been - read from stdout/stdin (as opposed to waitForFinished(), which measures time - since it was invoked). It is thus also suitable for slow processes that - continuously output data (like version system operations). - - The property timeOutMessageBoxEnabled influences whether a message box is - shown asking the user if they want to kill the process on timeout (default: false). - - There are also static utility functions for dealing with fully synchronous - processes, like reading the output with correct timeout handling. - - Caution: This class should NOT be used if there is a chance that the process - triggers opening dialog boxes (for example, by file watchers triggering), - as this will cause event loop problems. -*/ - -QString Process::exitMessage() const -{ - const QString fullCmd = commandLine().toUserOutput(); - switch (result()) { - case ProcessResult::FinishedWithSuccess: - return Tr::tr("The command \"%1\" finished successfully.").arg(fullCmd); - case ProcessResult::FinishedWithError: - return Tr::tr("The command \"%1\" terminated with exit code %2.") - .arg(fullCmd).arg(exitCode()); - case ProcessResult::TerminatedAbnormally: - return Tr::tr("The command \"%1\" terminated abnormally.").arg(fullCmd); - case ProcessResult::StartFailed: - return Tr::tr("The command \"%1\" could not be started.").arg(fullCmd); - case ProcessResult::Hang: - return Tr::tr("The command \"%1\" did not respond within the timeout limit (%2 s).") - .arg(fullCmd).arg(d->m_maxHangTimerCount); - } - return {}; -} - -QByteArray Process::allRawOutput() const -{ - QTC_CHECK(d->m_stdOut.keepRawData); - QTC_CHECK(d->m_stdErr.keepRawData); - if (!d->m_stdOut.rawData.isEmpty() && !d->m_stdErr.rawData.isEmpty()) { - QByteArray result = d->m_stdOut.rawData; - if (!result.endsWith('\n')) - result += '\n'; - result += d->m_stdErr.rawData; - return result; - } - return !d->m_stdOut.rawData.isEmpty() ? d->m_stdOut.rawData : d->m_stdErr.rawData; -} - -QString Process::allOutput() const -{ - QTC_CHECK(d->m_stdOut.keepRawData); - QTC_CHECK(d->m_stdErr.keepRawData); - const QString out = cleanedStdOut(); - const QString err = cleanedStdErr(); - - if (!out.isEmpty() && !err.isEmpty()) { - QString result = out; - if (!result.endsWith('\n')) - result += '\n'; - result += err; - return result; - } - return !out.isEmpty() ? out : err; -} - -QByteArray Process::rawStdOut() const -{ - QTC_CHECK(d->m_stdOut.keepRawData); - return d->m_stdOut.rawData; -} - -QString Process::stdOut() const -{ - QTC_CHECK(d->m_stdOut.keepRawData); - return d->m_codec->toUnicode(d->m_stdOut.rawData); -} - -QString Process::stdErr() const -{ - QTC_CHECK(d->m_stdErr.keepRawData); - return d->m_codec->toUnicode(d->m_stdErr.rawData); -} - -QString Process::cleanedStdOut() const -{ - return Utils::normalizeNewlines(stdOut()); -} - -QString Process::cleanedStdErr() const -{ - return Utils::normalizeNewlines(stdErr()); -} - -static QStringList splitLines(const QString &text) -{ - QStringList result = text.split('\n'); - for (QString &line : result) { - if (line.endsWith('\r')) - line.chop(1); - } - return result; -} - -const QStringList Process::stdOutLines() const -{ - return splitLines(cleanedStdOut()); -} - -const QStringList Process::stdErrLines() const -{ - return splitLines(cleanedStdErr()); -} - -QTCREATOR_UTILS_EXPORT QDebug operator<<(QDebug str, const Process &r) -{ - QDebug nsp = str.nospace(); - nsp << "QtcProcess: result=" - << int(r.d->m_result) << " ex=" << r.exitCode() << '\n' - << r.d->m_stdOut.rawData.size() << " bytes stdout, stderr=" << r.d->m_stdErr.rawData << '\n'; - return str; -} - -void ChannelBuffer::clearForRun() -{ - rawData.clear(); - codecState.reset(new QTextCodec::ConverterState); - incompleteLineBuffer.clear(); -} - -/* Check for complete lines read from the device and return them, moving the - * buffer position. */ -void ChannelBuffer::append(const QByteArray &text) -{ - if (text.isEmpty()) - return; - - if (keepRawData) - rawData += text; - - // Line-wise operation below: - if (!outputCallback) - return; - - // Convert and append the new input to the buffer of incomplete lines - incompleteLineBuffer.append(codec->toUnicode(text.constData(), text.size(), codecState.get())); - - do { - // Any completed lines in the incompleteLineBuffer? - int pos = -1; - if (emitSingleLines) { - const int posn = incompleteLineBuffer.indexOf('\n'); - const int posr = incompleteLineBuffer.indexOf('\r'); - if (posn != -1) { - if (posr != -1) { - if (posn == posr + 1) - pos = posn; // \r followed by \n -> line end, use the \n. - else - pos = qMin(posr, posn); // free floating \r and \n: Use the first one. - } else { - pos = posn; - } - } else { - pos = posr; // Make sure internal '\r' triggers a line output - } - } else { - pos = qMax(incompleteLineBuffer.lastIndexOf('\n'), - incompleteLineBuffer.lastIndexOf('\r')); - } - - if (pos == -1) - break; - - // Get completed lines and remove them from the incompleteLinesBuffer: - const QString line = Utils::normalizeNewlines(incompleteLineBuffer.left(pos + 1)); - incompleteLineBuffer = incompleteLineBuffer.mid(pos + 1); - - QTC_ASSERT(outputCallback, return); - outputCallback(line); - - if (!emitSingleLines) - break; - } while (true); -} - -void ChannelBuffer::handleRest() -{ - if (outputCallback && !incompleteLineBuffer.isEmpty()) { - outputCallback(incompleteLineBuffer); - incompleteLineBuffer.clear(); - } -} - -void Process::setTimeoutS(int timeoutS) -{ - if (timeoutS > 0) - d->m_maxHangTimerCount = qMax(2, timeoutS); - else - d->m_maxHangTimerCount = INT_MAX / 1000; -} - -int Process::timeoutS() const -{ - return d->m_maxHangTimerCount; -} - -void Process::setCodec(QTextCodec *c) -{ - QTC_ASSERT(c, return); - d->m_codec = c; -} - -void Process::setTimeOutMessageBoxEnabled(bool v) -{ - d->m_timeOutMessageBoxEnabled = v; -} - -void Process::setExitCodeInterpreter(const ExitCodeInterpreter &interpreter) -{ - d->m_exitCodeInterpreter = interpreter; -} - -void Process::setWriteData(const QByteArray &writeData) -{ - d->m_setup.m_writeData = writeData; -} - -void Process::runBlocking(EventLoopMode eventLoopMode) -{ - // Attach a dynamic property with info about blocking type - d->storeEventLoopDebugInfo(int(eventLoopMode)); - - QDateTime startTime; - static const int blockingThresholdMs = qtcEnvironmentVariableIntValue("QTC_PROCESS_THRESHOLD"); - if (blockingThresholdMs > 0 && isMainThread()) - startTime = QDateTime::currentDateTime(); - Process::start(); - - // Remove the dynamic property so that it's not reused in subseqent start() - d->storeEventLoopDebugInfo({}); - - if (eventLoopMode == EventLoopMode::On) { - // Start failure is triggered immediately if the executable cannot be found in the path. - // In this case the process is left in NotRunning state. - // Do not start the event loop in that case. - if (state() == QProcess::Starting) { - QTimer timer(this); - connect(&timer, &QTimer::timeout, d, &QtcProcessPrivate::slotTimeout); - timer.setInterval(1000); - timer.start(); -#ifdef QT_GUI_LIB - if (isMainThread()) - QApplication::setOverrideCursor(Qt::WaitCursor); -#endif - QEventLoop eventLoop(this); - QTC_ASSERT(!d->m_eventLoop, return); - d->m_eventLoop = &eventLoop; - eventLoop.exec(QEventLoop::ExcludeUserInputEvents); - d->m_eventLoop = nullptr; - timer.stop(); -#ifdef QT_GUI_LIB - if (isMainThread()) - QApplication::restoreOverrideCursor(); -#endif - } - } else { - if (!waitForStarted(d->m_maxHangTimerCount * 1000)) { - d->m_result = ProcessResult::StartFailed; - return; - } - if (!waitForFinished(d->m_maxHangTimerCount * 1000)) { - d->m_result = ProcessResult::Hang; - terminate(); - if (!waitForFinished(1000)) { - kill(); - waitForFinished(1000); - } - } - } - if (blockingThresholdMs > 0) { - const int timeDiff = startTime.msecsTo(QDateTime::currentDateTime()); - if (timeDiff > blockingThresholdMs && isMainThread()) { - qWarning() << "Blocking process " << d->m_setup.m_commandLine << "took" << timeDiff - << "ms, longer than threshold" << blockingThresholdMs; - } - } -} - -void Process::setStdOutCallback(const TextChannelCallback &callback) -{ - d->m_stdOut.outputCallback = callback; - d->m_stdOut.emitSingleLines = false; -} - -void Process::setStdOutLineCallback(const TextChannelCallback &callback) -{ - d->m_stdOut.outputCallback = callback; - d->m_stdOut.emitSingleLines = true; - d->m_stdOut.keepRawData = false; -} - -void Process::setStdErrCallback(const TextChannelCallback &callback) -{ - d->m_stdErr.outputCallback = callback; - d->m_stdErr.emitSingleLines = false; -} - -void Process::setStdErrLineCallback(const TextChannelCallback &callback) -{ - d->m_stdErr.outputCallback = callback; - d->m_stdErr.emitSingleLines = true; - d->m_stdErr.keepRawData = false; -} - -void Process::setTextChannelMode(Channel channel, TextChannelMode mode) -{ - const TextChannelCallback outputCb = [this](const QString &text) { - GuardLocker locker(d->m_guard); - emit textOnStandardOutput(text); - }; - const TextChannelCallback errorCb = [this](const QString &text) { - GuardLocker locker(d->m_guard); - emit textOnStandardError(text); - }; - const TextChannelCallback callback = (channel == Channel::Output) ? outputCb : errorCb; - ChannelBuffer *buffer = channel == Channel::Output ? &d->m_stdOut : &d->m_stdErr; - QTC_ASSERT(buffer->m_textChannelMode == TextChannelMode::Off, qWarning() - << "QtcProcess::setTextChannelMode(): Changing text channel mode for" - << (channel == Channel::Output ? "Output": "Error") - << "channel while it was previously set for this channel."); - buffer->m_textChannelMode = mode; - switch (mode) { - case TextChannelMode::Off: - buffer->outputCallback = {}; - buffer->emitSingleLines = true; - buffer->keepRawData = true; - break; - case TextChannelMode::SingleLine: - buffer->outputCallback = callback; - buffer->emitSingleLines = true; - buffer->keepRawData = false; - break; - case TextChannelMode::MultiLine: - buffer->outputCallback = callback; - buffer->emitSingleLines = false; - buffer->keepRawData = true; - break; - } -} - -TextChannelMode Process::textChannelMode(Channel channel) const -{ - ChannelBuffer *buffer = channel == Channel::Output ? &d->m_stdOut : &d->m_stdErr; - return buffer->m_textChannelMode; -} - -void QtcProcessPrivate::slotTimeout() -{ - if (!m_waitingForUser && (++m_hangTimerCount > m_maxHangTimerCount)) { - if (debug) - qDebug() << Q_FUNC_INFO << "HANG detected, killing"; - m_waitingForUser = true; - const bool terminate = !m_timeOutMessageBoxEnabled || askToKill(m_setup.m_commandLine); - m_waitingForUser = false; - if (terminate) { - q->stop(); - q->waitForFinished(); - m_result = ProcessResult::Hang; - } else { - m_hangTimerCount = 0; - } - } else { - if (debug) - qDebug() << Q_FUNC_INFO << m_hangTimerCount; - } -} - -void QtcProcessPrivate::handleStarted(qint64 processId, qint64 applicationMainThreadId) -{ - QTC_CHECK(m_state == QProcess::Starting); - m_state = QProcess::Running; - - m_processId = processId; - m_applicationMainThreadId = applicationMainThreadId; - emitGuardedSignal(&Process::started); -} - -void QtcProcessPrivate::handleReadyRead(const QByteArray &outputData, const QByteArray &errorData) -{ - QTC_CHECK(m_state == QProcess::Running); - - // TODO: check why we need this timer? - m_hangTimerCount = 0; - // TODO: store a copy of m_processChannelMode on start()? Currently we assert that state - // is NotRunning when setting the process channel mode. - - if (!outputData.isEmpty()) { - if (m_process->m_setup.m_processChannelMode == QProcess::ForwardedOutputChannel - || m_process->m_setup.m_processChannelMode == QProcess::ForwardedChannels) { - std::cout << outputData.constData() << std::flush; - } else { - m_stdOut.append(outputData); - emitGuardedSignal(&Process::readyReadStandardOutput); - } - } - if (!errorData.isEmpty()) { - if (m_process->m_setup.m_processChannelMode == QProcess::ForwardedErrorChannel - || m_process->m_setup.m_processChannelMode == QProcess::ForwardedChannels) { - std::cerr << errorData.constData() << std::flush; - } else { - m_stdErr.append(errorData); - emitGuardedSignal(&Process::readyReadStandardError); - } - } -} - -void QtcProcessPrivate::handleDone(const ProcessResultData &data) -{ - m_killTimer.stop(); - const bool wasCanceled = m_resultData.m_canceledByUser; - m_resultData = data; - m_resultData.m_canceledByUser = wasCanceled; - - switch (m_state) { - case QProcess::NotRunning: - QTC_CHECK(false); // Can't happen - break; - case QProcess::Starting: - QTC_CHECK(m_resultData.m_error == QProcess::FailedToStart); - break; - case QProcess::Running: - QTC_CHECK(m_resultData.m_error != QProcess::FailedToStart); - break; - } - m_state = QProcess::NotRunning; - - // This code (255) is being returned by QProcess when FailedToStart error occurred - if (m_resultData.m_error == QProcess::FailedToStart) - m_resultData.m_exitCode = 0xFF; - - // HACK: See QIODevice::errorString() implementation. - if (m_resultData.m_error == QProcess::UnknownError) - m_resultData.m_errorString.clear(); - else if (m_result != ProcessResult::Hang) - m_result = ProcessResult::StartFailed; - - if (debug) - qDebug() << Q_FUNC_INFO << m_resultData.m_exitCode << m_resultData.m_exitStatus; - m_hangTimerCount = 0; - - if (m_resultData.m_error != QProcess::FailedToStart) { - switch (m_resultData.m_exitStatus) { - case QProcess::NormalExit: - m_result = interpretExitCode(m_resultData.m_exitCode); - break; - case QProcess::CrashExit: - // Was hang detected before and killed? - if (m_result != ProcessResult::Hang) - m_result = ProcessResult::TerminatedAbnormally; - break; - } - } - if (m_eventLoop) - m_eventLoop->quit(); - - m_stdOut.handleRest(); - m_stdErr.handleRest(); - - emitGuardedSignal(&Process::done); - m_processId = 0; - m_applicationMainThreadId = 0; -} - -static QString blockingMessage(const QVariant &variant) -{ - if (!variant.isValid()) - return "non blocking"; - if (variant.toInt() == int(EventLoopMode::On)) - return "blocking with event loop"; - return "blocking without event loop"; -} - -void QtcProcessPrivate::setupDebugLog() -{ - if (!processLog().isDebugEnabled()) - return; - - auto now = [] { - using namespace std::chrono; - return duration_cast(system_clock::now().time_since_epoch()).count(); - }; - - connect(q, &Process::starting, this, [=] { - const quint64 msNow = now(); - setProperty(QTC_PROCESS_STARTTIME, msNow); - - static std::atomic_int startCounter = 0; - const int currentNumber = startCounter.fetch_add(1); - qCDebug(processLog).nospace().noquote() - << "Process " << currentNumber << " starting (" - << qPrintable(blockingMessage(property(QTC_PROCESS_BLOCKING_TYPE))) - << "): " << m_setup.m_commandLine.toUserOutput(); - setProperty(QTC_PROCESS_NUMBER, currentNumber); - }); - - connect(q, &Process::done, this, [=] { - if (!m_process.get()) - return; - const QVariant n = property(QTC_PROCESS_NUMBER); - if (!n.isValid()) - return; - const quint64 msNow = now(); - const quint64 msStarted = property(QTC_PROCESS_STARTTIME).toULongLong(); - const quint64 msElapsed = msNow - msStarted; - - const int number = n.toInt(); - const QString stdOut = q->cleanedStdOut(); - const QString stdErr = q->cleanedStdErr(); - qCDebug(processLog).nospace() - << "Process " << number << " finished: result=" << int(m_result) - << ", ex=" << m_resultData.m_exitCode - << ", " << stdOut.size() << " bytes stdout: " << stdOut.left(20) - << ", " << stdErr.size() << " bytes stderr: " << stdErr.left(1000) - << ", " << msElapsed << " ms elapsed"; - if (processStdoutLog().isDebugEnabled() && !stdOut.isEmpty()) - qCDebug(processStdoutLog).nospace() << "Process " << number << " sdout: " << stdOut; - if (processStderrLog().isDebugEnabled() && !stdErr.isEmpty()) - qCDebug(processStderrLog).nospace() << "Process " << number << " stderr: " << stdErr; - }); -} - -void QtcProcessPrivate::storeEventLoopDebugInfo(const QVariant &value) -{ - if (processLog().isDebugEnabled()) - setProperty(QTC_PROCESS_BLOCKING_TYPE, value); -} - -ProcessTaskAdapter::ProcessTaskAdapter() -{ - connect(task(), &Process::done, this, [this] { - emit done(task()->result() == ProcessResult::FinishedWithSuccess); - }); -} - -void ProcessTaskAdapter::start() -{ - task()->start(); -} - -} // namespace Utils - -#include "qtcprocess.moc" diff --git a/src/libs/utils/qtcprocess.h b/src/libs/utils/qtcprocess.h deleted file mode 100644 index f89b6f9b22..0000000000 --- a/src/libs/utils/qtcprocess.h +++ /dev/null @@ -1,219 +0,0 @@ -// Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -#pragma once - -#include "utils_global.h" - -#include "commandline.h" -#include "processenums.h" -#include "tasktree.h" - -#include - -QT_BEGIN_NAMESPACE -class QDebug; -class QTextCodec; -QT_END_NAMESPACE - -class tst_QtcProcess; - -namespace Utils { - -namespace Internal { class QtcProcessPrivate; } -namespace Pty { class Data; } - -class Environment; -class DeviceProcessHooks; -class ProcessInterface; -class ProcessResultData; - -class QTCREATOR_UTILS_EXPORT Process final : public QObject -{ - Q_OBJECT - -public: - explicit Process(QObject *parent = nullptr); - ~Process(); - - // ProcessInterface related - - void start(); - - void terminate(); - void kill(); - void interrupt(); - void kickoffProcess(); - void closeWriteChannel(); - void close(); - void stop(); - - QString readAllStandardOutput(); - QString readAllStandardError(); - - QByteArray readAllRawStandardOutput(); - QByteArray readAllRawStandardError(); - - qint64 write(const QString &input); - qint64 writeRaw(const QByteArray &input); - - qint64 processId() const; - qint64 applicationMainThreadId() const; - - QProcess::ProcessState state() const; - ProcessResultData resultData() const; - - int exitCode() const; - QProcess::ExitStatus exitStatus() const; - - QProcess::ProcessError error() const; - QString errorString() const; - - bool waitForStarted(int msecs = 30000); - bool waitForReadyRead(int msecs = 30000); - bool waitForFinished(int msecs = 30000); - - // ProcessSetupData related - - void setProcessImpl(ProcessImpl processImpl); - - void setPtyData(const std::optional &data); - std::optional ptyData() const; - - void setTerminalMode(TerminalMode mode); - TerminalMode terminalMode() const; - bool usesTerminal() const { return terminalMode() != TerminalMode::Off; } - - void setProcessMode(ProcessMode processMode); - ProcessMode processMode() const; - - void setEnvironment(const Environment &env); // Main process - const Environment &environment() const; - - void setControlEnvironment(const Environment &env); // Possible helper process (ssh on host etc) - const Environment &controlEnvironment() const; - - void setCommand(const CommandLine &cmdLine); - const CommandLine &commandLine() const; - - void setWorkingDirectory(const FilePath &dir); - FilePath workingDirectory() const; - - void setWriteData(const QByteArray &writeData); - - void setUseCtrlCStub(bool enabled); // release only - void setLowPriority(); - void setDisableUnixTerminal(); - void setRunAsRoot(bool on); - bool isRunAsRoot() const; - void setAbortOnMetaChars(bool abort); - - QProcess::ProcessChannelMode processChannelMode() const; - 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; - - void setReaperTimeout(int msecs); - int reaperTimeout() const; - - 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); - - static bool startDetached(const CommandLine &cmd, const FilePath &workingDirectory = {}, - qint64 *pid = nullptr); - - // Starts the command and waits for finish. - // User input processing is enabled when EventLoopMode::On was passed. - void runBlocking(EventLoopMode eventLoopMode = EventLoopMode::Off); - - /* Timeout for hanging processes (triggers after no more output - * occurs on stderr/stdout). */ - void setTimeoutS(int timeoutS); - int timeoutS() const; - - // TODO: We should specify the purpose of the codec, e.g. setCodecForStandardChannel() - void setCodec(QTextCodec *c); - void setTimeOutMessageBoxEnabled(bool); - void setExitCodeInterpreter(const ExitCodeInterpreter &interpreter); - - 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; - - bool readDataFromProcess(QByteArray *stdOut, QByteArray *stdErr, int timeoutS = 30); - - ProcessResult result() const; - - QByteArray allRawOutput() const; - QString allOutput() const; - - QByteArray rawStdOut() const; - - QString stdOut() const; // possibly with CR - QString stdErr() const; // possibly with CR - - 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 - - const QStringList stdOutLines() const; // split, CR removed - const QStringList stdErrLines() const; // split, CR removed - - QString exitMessage() const; - - QString toStandaloneCommandLine() const; - - void setCreateConsoleOnWindows(bool create); - bool createConsoleOnWindows() const; - -signals: - void starting(); // On NotRunning -> Starting state transition - void started(); // On Starting -> Running state transition - void done(); // On Starting | Running -> NotRunning state transition - void readyReadStandardOutput(); - void readyReadStandardError(); - void textOnStandardOutput(const QString &text); - void textOnStandardError(const QString &text); - -private: - friend QTCREATOR_UTILS_EXPORT QDebug operator<<(QDebug str, const Process &r); - - friend class Internal::QtcProcessPrivate; - Internal::QtcProcessPrivate *d = nullptr; -}; - -class DeviceProcessHooks -{ -public: - std::function processImplHook; - std::function systemEnvironmentForBinary; -}; - -class QTCREATOR_UTILS_EXPORT ProcessTaskAdapter : public Tasking::TaskAdapter -{ -public: - ProcessTaskAdapter(); - void start() final; -}; - -} // namespace Utils - -QTC_DECLARE_CUSTOM_TASK(ProcessTask, Utils::ProcessTaskAdapter); diff --git a/src/libs/utils/terminalhooks.cpp b/src/libs/utils/terminalhooks.cpp index c7cab04028..b6faae765d 100644 --- a/src/libs/utils/terminalhooks.cpp +++ b/src/libs/utils/terminalhooks.cpp @@ -4,7 +4,7 @@ #include "terminalhooks.h" #include "filepath.h" -#include "qtcprocess.h" +#include "process.h" #include "terminalcommand.h" #include "terminalinterface.h" diff --git a/src/libs/utils/utils.qbs b/src/libs/utils/utils.qbs index ba2bc175f8..4f628616a1 100644 --- a/src/libs/utils/utils.qbs +++ b/src/libs/utils/utils.qbs @@ -239,6 +239,8 @@ Project { "port.h", "portlist.cpp", "portlist.h", + "process.cpp", + "process.h", "processenums.h", "processhandle.cpp", "processhandle.h", @@ -262,8 +264,6 @@ Project { "qtcassert.h", "qtcolorbutton.cpp", "qtcolorbutton.h", - "qtcprocess.cpp", - "qtcprocess.h", "qtcsettings.cpp", "qtcsettings.h", "reloadpromptutils.cpp", diff --git a/src/plugins/android/androidavdmanager.cpp b/src/plugins/android/androidavdmanager.cpp index a5f71a95cd..2e7067ca27 100644 --- a/src/plugins/android/androidavdmanager.cpp +++ b/src/plugins/android/androidavdmanager.cpp @@ -11,8 +11,8 @@ #include #include +#include #include -#include #include #include diff --git a/src/plugins/android/androidbuildapkstep.cpp b/src/plugins/android/androidbuildapkstep.cpp index c79282e536..b27730b45b 100644 --- a/src/plugins/android/androidbuildapkstep.cpp +++ b/src/plugins/android/androidbuildapkstep.cpp @@ -36,7 +36,7 @@ #include #include #include -#include +#include #include #include diff --git a/src/plugins/android/androidconfigurations.cpp b/src/plugins/android/androidconfigurations.cpp index eccfb2041e..9c444f6e75 100644 --- a/src/plugins/android/androidconfigurations.cpp +++ b/src/plugins/android/androidconfigurations.cpp @@ -34,8 +34,8 @@ #include #include #include +#include #include -#include #include #include diff --git a/src/plugins/android/androidcreatekeystorecertificate.cpp b/src/plugins/android/androidcreatekeystorecertificate.cpp index 09858e3603..67e6c8ff83 100644 --- a/src/plugins/android/androidcreatekeystorecertificate.cpp +++ b/src/plugins/android/androidcreatekeystorecertificate.cpp @@ -7,7 +7,7 @@ #include #include -#include +#include #include #include diff --git a/src/plugins/android/androiddebugsupport.cpp b/src/plugins/android/androiddebugsupport.cpp index 138740e4a3..bb4fc51b98 100644 --- a/src/plugins/android/androiddebugsupport.cpp +++ b/src/plugins/android/androiddebugsupport.cpp @@ -21,7 +21,7 @@ #include #include -#include +#include #include #include diff --git a/src/plugins/android/androiddeployqtstep.cpp b/src/plugins/android/androiddeployqtstep.cpp index 2ba26ebc61..979efcb1af 100644 --- a/src/plugins/android/androiddeployqtstep.cpp +++ b/src/plugins/android/androiddeployqtstep.cpp @@ -38,8 +38,8 @@ #include #include #include +#include #include -#include #include #include diff --git a/src/plugins/android/androiddevice.cpp b/src/plugins/android/androiddevice.cpp index c1afae589b..a8ae3f8746 100644 --- a/src/plugins/android/androiddevice.cpp +++ b/src/plugins/android/androiddevice.cpp @@ -22,8 +22,8 @@ #include #include +#include #include -#include #include #include diff --git a/src/plugins/android/androidmanager.cpp b/src/plugins/android/androidmanager.cpp index 495f031be4..0ccca7c8f7 100644 --- a/src/plugins/android/androidmanager.cpp +++ b/src/plugins/android/androidmanager.cpp @@ -36,8 +36,8 @@ #include #include +#include #include -#include #include #include diff --git a/src/plugins/android/androidpackageinstallationstep.cpp b/src/plugins/android/androidpackageinstallationstep.cpp index e2f929f081..e29bac3476 100644 --- a/src/plugins/android/androidpackageinstallationstep.cpp +++ b/src/plugins/android/androidpackageinstallationstep.cpp @@ -22,7 +22,7 @@ #include #include -#include +#include #include #include diff --git a/src/plugins/android/androidqmlpreviewworker.cpp b/src/plugins/android/androidqmlpreviewworker.cpp index e489a1e1e7..d296dfe677 100644 --- a/src/plugins/android/androidqmlpreviewworker.cpp +++ b/src/plugins/android/androidqmlpreviewworker.cpp @@ -28,7 +28,7 @@ #include #include -#include +#include #include #include diff --git a/src/plugins/android/androidrunconfiguration.cpp b/src/plugins/android/androidrunconfiguration.cpp index ef469da2b6..e62145566a 100644 --- a/src/plugins/android/androidrunconfiguration.cpp +++ b/src/plugins/android/androidrunconfiguration.cpp @@ -18,8 +18,8 @@ #include #include +#include #include -#include #include using namespace ProjectExplorer; diff --git a/src/plugins/android/androidrunnerworker.cpp b/src/plugins/android/androidrunnerworker.cpp index 0e5f6c6f80..65ef869558 100644 --- a/src/plugins/android/androidrunnerworker.cpp +++ b/src/plugins/android/androidrunnerworker.cpp @@ -23,7 +23,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/src/plugins/android/androidsdkmanager.cpp b/src/plugins/android/androidsdkmanager.cpp index 61354888fd..1839f7c21c 100644 --- a/src/plugins/android/androidsdkmanager.cpp +++ b/src/plugins/android/androidsdkmanager.cpp @@ -9,8 +9,8 @@ #include #include +#include #include -#include #include #include diff --git a/src/plugins/android/androidsettingswidget.cpp b/src/plugins/android/androidsettingswidget.cpp index 62fed62a81..2ebc61802d 100644 --- a/src/plugins/android/androidsettingswidget.cpp +++ b/src/plugins/android/androidsettingswidget.cpp @@ -17,8 +17,8 @@ #include #include #include +#include #include -#include #include #include diff --git a/src/plugins/android/androidsignaloperation.cpp b/src/plugins/android/androidsignaloperation.cpp index a3fdfeeb83..b6a7699dd4 100644 --- a/src/plugins/android/androidsignaloperation.cpp +++ b/src/plugins/android/androidsignaloperation.cpp @@ -4,8 +4,8 @@ #include "androidconfigurations.h" #include "androidsignaloperation.h" +#include #include -#include using namespace Utils; diff --git a/src/plugins/autotest/boost/boosttestoutputreader.cpp b/src/plugins/autotest/boost/boosttestoutputreader.cpp index f91dd25b21..96b0dffd61 100644 --- a/src/plugins/autotest/boost/boosttestoutputreader.cpp +++ b/src/plugins/autotest/boost/boosttestoutputreader.cpp @@ -9,8 +9,8 @@ #include "../autotesttr.h" #include "../testtreeitem.h" +#include #include -#include #include #include diff --git a/src/plugins/autotest/gtest/gtestoutputreader.cpp b/src/plugins/autotest/gtest/gtestoutputreader.cpp index 66a4935622..12e0424016 100644 --- a/src/plugins/autotest/gtest/gtestoutputreader.cpp +++ b/src/plugins/autotest/gtest/gtestoutputreader.cpp @@ -8,7 +8,7 @@ #include "../autotesttr.h" #include -#include +#include #include diff --git a/src/plugins/autotest/testoutputreader.cpp b/src/plugins/autotest/testoutputreader.cpp index 48bab93066..cef36c90e7 100644 --- a/src/plugins/autotest/testoutputreader.cpp +++ b/src/plugins/autotest/testoutputreader.cpp @@ -6,8 +6,8 @@ #include "autotesttr.h" #include "testtreeitem.h" +#include #include -#include #include diff --git a/src/plugins/autotest/testrunner.cpp b/src/plugins/autotest/testrunner.cpp index c0ca216533..2d9be97b43 100644 --- a/src/plugins/autotest/testrunner.cpp +++ b/src/plugins/autotest/testrunner.cpp @@ -33,7 +33,7 @@ #include #include #include -#include +#include #include #include diff --git a/src/plugins/autotoolsprojectmanager/makefileparser.cpp b/src/plugins/autotoolsprojectmanager/makefileparser.cpp index 9bbccdb86a..e1cac6b186 100644 --- a/src/plugins/autotoolsprojectmanager/makefileparser.cpp +++ b/src/plugins/autotoolsprojectmanager/makefileparser.cpp @@ -5,8 +5,8 @@ #include "autotoolsprojectmanagertr.h" +#include #include -#include #include #include diff --git a/src/plugins/baremetal/baremetaldebugsupport.cpp b/src/plugins/baremetal/baremetaldebugsupport.cpp index c236ab32f2..4475be0b96 100644 --- a/src/plugins/baremetal/baremetaldebugsupport.cpp +++ b/src/plugins/baremetal/baremetaldebugsupport.cpp @@ -24,8 +24,8 @@ #include #include +#include #include -#include using namespace Debugger; using namespace ProjectExplorer; diff --git a/src/plugins/baremetal/debugservers/gdb/jlinkgdbserverprovider.cpp b/src/plugins/baremetal/debugservers/gdb/jlinkgdbserverprovider.cpp index d631923788..c1ee31b710 100644 --- a/src/plugins/baremetal/debugservers/gdb/jlinkgdbserverprovider.cpp +++ b/src/plugins/baremetal/debugservers/gdb/jlinkgdbserverprovider.cpp @@ -9,8 +9,8 @@ #include #include +#include #include -#include #include #include diff --git a/src/plugins/baremetal/debugservers/gdb/openocdgdbserverprovider.cpp b/src/plugins/baremetal/debugservers/gdb/openocdgdbserverprovider.cpp index 03933cff50..ca7f25e56f 100644 --- a/src/plugins/baremetal/debugservers/gdb/openocdgdbserverprovider.cpp +++ b/src/plugins/baremetal/debugservers/gdb/openocdgdbserverprovider.cpp @@ -9,8 +9,8 @@ #include #include +#include #include -#include #include #include diff --git a/src/plugins/baremetal/debugservers/uvsc/uvscserverprovider.h b/src/plugins/baremetal/debugservers/uvsc/uvscserverprovider.h index 6f4275769e..4c14ee7b7c 100644 --- a/src/plugins/baremetal/debugservers/uvsc/uvscserverprovider.h +++ b/src/plugins/baremetal/debugservers/uvsc/uvscserverprovider.h @@ -10,7 +10,7 @@ #include // for RunWorker -#include +#include namespace Utils { class PathChooser; } diff --git a/src/plugins/baremetal/iarewtoolchain.cpp b/src/plugins/baremetal/iarewtoolchain.cpp index 392d4e8234..c6653fefbb 100644 --- a/src/plugins/baremetal/iarewtoolchain.cpp +++ b/src/plugins/baremetal/iarewtoolchain.cpp @@ -15,8 +15,8 @@ #include #include #include +#include #include -#include #include #include diff --git a/src/plugins/baremetal/keiltoolchain.cpp b/src/plugins/baremetal/keiltoolchain.cpp index e9662ff031..3bb2423ab2 100644 --- a/src/plugins/baremetal/keiltoolchain.cpp +++ b/src/plugins/baremetal/keiltoolchain.cpp @@ -15,8 +15,8 @@ #include #include #include +#include #include -#include #include #include diff --git a/src/plugins/baremetal/sdcctoolchain.cpp b/src/plugins/baremetal/sdcctoolchain.cpp index 14b20657de..a35a468d20 100644 --- a/src/plugins/baremetal/sdcctoolchain.cpp +++ b/src/plugins/baremetal/sdcctoolchain.cpp @@ -15,8 +15,8 @@ #include #include #include +#include #include -#include #include #include diff --git a/src/plugins/beautifier/abstractsettings.cpp b/src/plugins/beautifier/abstractsettings.cpp index 17e36d279c..fa621fdebc 100644 --- a/src/plugins/beautifier/abstractsettings.cpp +++ b/src/plugins/beautifier/abstractsettings.cpp @@ -14,7 +14,7 @@ #include #include #include -#include +#include #include #include diff --git a/src/plugins/beautifier/artisticstyle/artisticstylesettings.cpp b/src/plugins/beautifier/artisticstyle/artisticstylesettings.cpp index b7d54de96f..42b91a785f 100644 --- a/src/plugins/beautifier/artisticstyle/artisticstylesettings.cpp +++ b/src/plugins/beautifier/artisticstyle/artisticstylesettings.cpp @@ -7,8 +7,8 @@ #include +#include #include -#include #include #include diff --git a/src/plugins/beautifier/beautifierplugin.cpp b/src/plugins/beautifier/beautifierplugin.cpp index 76db40daea..3057f2034a 100644 --- a/src/plugins/beautifier/beautifierplugin.cpp +++ b/src/plugins/beautifier/beautifierplugin.cpp @@ -31,8 +31,8 @@ #include #include #include +#include #include -#include #include #include diff --git a/src/plugins/beautifier/uncrustify/uncrustifysettings.cpp b/src/plugins/beautifier/uncrustify/uncrustifysettings.cpp index 243d63e049..a284d780b6 100644 --- a/src/plugins/beautifier/uncrustify/uncrustifysettings.cpp +++ b/src/plugins/beautifier/uncrustify/uncrustifysettings.cpp @@ -6,7 +6,7 @@ #include "../beautifierconstants.h" #include -#include +#include #include #include diff --git a/src/plugins/boot2qt/device-detection/qdbwatcher.cpp b/src/plugins/boot2qt/device-detection/qdbwatcher.cpp index 8a18a3b5ac..869b2d84fc 100644 --- a/src/plugins/boot2qt/device-detection/qdbwatcher.cpp +++ b/src/plugins/boot2qt/device-detection/qdbwatcher.cpp @@ -8,7 +8,7 @@ #include "../qdbutils.h" #include -#include +#include #include #include diff --git a/src/plugins/boot2qt/qdbdevice.cpp b/src/plugins/boot2qt/qdbdevice.cpp index dd767fbc7c..43783279d6 100644 --- a/src/plugins/boot2qt/qdbdevice.cpp +++ b/src/plugins/boot2qt/qdbdevice.cpp @@ -15,8 +15,8 @@ #include #include +#include #include -#include #include #include diff --git a/src/plugins/boot2qt/qdbdevicedebugsupport.cpp b/src/plugins/boot2qt/qdbdevicedebugsupport.cpp index 0aa4f74362..d6e198538f 100644 --- a/src/plugins/boot2qt/qdbdevicedebugsupport.cpp +++ b/src/plugins/boot2qt/qdbdevicedebugsupport.cpp @@ -13,7 +13,7 @@ #include #include -#include +#include #include using namespace Debugger; diff --git a/src/plugins/boot2qt/qdbmakedefaultappstep.cpp b/src/plugins/boot2qt/qdbmakedefaultappstep.cpp index b99d264066..4c18253fe1 100644 --- a/src/plugins/boot2qt/qdbmakedefaultappstep.cpp +++ b/src/plugins/boot2qt/qdbmakedefaultappstep.cpp @@ -14,7 +14,7 @@ #include #include -#include +#include using namespace ProjectExplorer; using namespace Utils; diff --git a/src/plugins/boot2qt/qdbplugin.cpp b/src/plugins/boot2qt/qdbplugin.cpp index 6ce706e3c1..8c806cb158 100644 --- a/src/plugins/boot2qt/qdbplugin.cpp +++ b/src/plugins/boot2qt/qdbplugin.cpp @@ -29,9 +29,9 @@ #include -#include #include -#include +#include +#include #include diff --git a/src/plugins/boot2qt/qdbstopapplicationstep.cpp b/src/plugins/boot2qt/qdbstopapplicationstep.cpp index a9fd0fb220..3707ef20bc 100644 --- a/src/plugins/boot2qt/qdbstopapplicationstep.cpp +++ b/src/plugins/boot2qt/qdbstopapplicationstep.cpp @@ -13,7 +13,7 @@ #include -#include +#include using namespace ProjectExplorer; using namespace Utils; diff --git a/src/plugins/clangtools/clangtoolruncontrol.cpp b/src/plugins/clangtools/clangtoolruncontrol.cpp index 39a27523a0..2f45588625 100644 --- a/src/plugins/clangtools/clangtoolruncontrol.cpp +++ b/src/plugins/clangtools/clangtoolruncontrol.cpp @@ -21,7 +21,7 @@ #include #include -#include +#include #include #include diff --git a/src/plugins/clangtools/clangtoolrunner.cpp b/src/plugins/clangtools/clangtoolrunner.cpp index 7c71acceb9..9d27e9f49b 100644 --- a/src/plugins/clangtools/clangtoolrunner.cpp +++ b/src/plugins/clangtools/clangtoolrunner.cpp @@ -11,8 +11,8 @@ #include #include +#include #include -#include #include #include diff --git a/src/plugins/clangtools/clangtoolsutils.cpp b/src/plugins/clangtools/clangtoolsutils.cpp index 6b5e373daa..7a812d3750 100644 --- a/src/plugins/clangtools/clangtoolsutils.cpp +++ b/src/plugins/clangtools/clangtoolsutils.cpp @@ -18,8 +18,8 @@ #include #include #include +#include #include -#include #include diff --git a/src/plugins/clangtools/executableinfo.cpp b/src/plugins/clangtools/executableinfo.cpp index 0b5d649cf5..22898b5734 100644 --- a/src/plugins/clangtools/executableinfo.cpp +++ b/src/plugins/clangtools/executableinfo.cpp @@ -7,7 +7,7 @@ #include #include -#include +#include #include #include diff --git a/src/plugins/clearcase/clearcaseplugin.cpp b/src/plugins/clearcase/clearcaseplugin.cpp index f32e502c1b..1b3b4d2ae9 100644 --- a/src/plugins/clearcase/clearcaseplugin.cpp +++ b/src/plugins/clearcase/clearcaseplugin.cpp @@ -35,8 +35,8 @@ #include #include #include +#include #include -#include #include #include diff --git a/src/plugins/clearcase/clearcasesync.cpp b/src/plugins/clearcase/clearcasesync.cpp index 82e1b7571d..053c387ee9 100644 --- a/src/plugins/clearcase/clearcasesync.cpp +++ b/src/plugins/clearcase/clearcasesync.cpp @@ -10,8 +10,8 @@ #include #include +#include #include -#include #include diff --git a/src/plugins/cmakeprojectmanager/cmakebuildsystem.cpp b/src/plugins/cmakeprojectmanager/cmakebuildsystem.cpp index 146c2f853c..20c8513321 100644 --- a/src/plugins/cmakeprojectmanager/cmakebuildsystem.cpp +++ b/src/plugins/cmakeprojectmanager/cmakebuildsystem.cpp @@ -46,8 +46,8 @@ #include #include #include +#include #include -#include #include #include diff --git a/src/plugins/cmakeprojectmanager/cmakeformattersettings.cpp b/src/plugins/cmakeprojectmanager/cmakeformattersettings.cpp index 4bb2218340..258954fa11 100644 --- a/src/plugins/cmakeprojectmanager/cmakeformattersettings.cpp +++ b/src/plugins/cmakeprojectmanager/cmakeformattersettings.cpp @@ -10,7 +10,7 @@ #include #include #include -#include +#include namespace CMakeProjectManager { namespace Internal { diff --git a/src/plugins/cmakeprojectmanager/cmakeprocess.cpp b/src/plugins/cmakeprojectmanager/cmakeprocess.cpp index 6b8270db6c..5922f92045 100644 --- a/src/plugins/cmakeprojectmanager/cmakeprocess.cpp +++ b/src/plugins/cmakeprojectmanager/cmakeprocess.cpp @@ -14,8 +14,8 @@ #include #include +#include #include -#include #include using namespace Core; diff --git a/src/plugins/cmakeprojectmanager/cmakeprojectimporter.cpp b/src/plugins/cmakeprojectmanager/cmakeprojectimporter.cpp index 52da1adc8a..69cdda4c52 100644 --- a/src/plugins/cmakeprojectmanager/cmakeprojectimporter.cpp +++ b/src/plugins/cmakeprojectmanager/cmakeprojectimporter.cpp @@ -20,8 +20,8 @@ #include #include +#include #include -#include #include #include diff --git a/src/plugins/cmakeprojectmanager/cmaketool.cpp b/src/plugins/cmakeprojectmanager/cmaketool.cpp index eae44c1563..9239ea5417 100644 --- a/src/plugins/cmakeprojectmanager/cmaketool.cpp +++ b/src/plugins/cmakeprojectmanager/cmaketool.cpp @@ -10,8 +10,8 @@ #include #include +#include #include -#include #include #include diff --git a/src/plugins/cmakeprojectmanager/fileapidataextractor.cpp b/src/plugins/cmakeprojectmanager/fileapidataextractor.cpp index d6438e5d22..c6f8f1225c 100644 --- a/src/plugins/cmakeprojectmanager/fileapidataextractor.cpp +++ b/src/plugins/cmakeprojectmanager/fileapidataextractor.cpp @@ -14,8 +14,8 @@ #include #include +#include #include -#include #include #include diff --git a/src/plugins/coreplugin/dialogs/externaltoolconfig.cpp b/src/plugins/coreplugin/dialogs/externaltoolconfig.cpp index 0d4404c714..59237aad79 100644 --- a/src/plugins/coreplugin/dialogs/externaltoolconfig.cpp +++ b/src/plugins/coreplugin/dialogs/externaltoolconfig.cpp @@ -18,8 +18,8 @@ #include #include #include +#include #include -#include #include #include diff --git a/src/plugins/coreplugin/externaltool.cpp b/src/plugins/coreplugin/externaltool.cpp index 14e4d51120..6cafa6ff88 100644 --- a/src/plugins/coreplugin/externaltool.cpp +++ b/src/plugins/coreplugin/externaltool.cpp @@ -16,8 +16,8 @@ #include #include #include +#include #include -#include #include #include diff --git a/src/plugins/coreplugin/fileutils.cpp b/src/plugins/coreplugin/fileutils.cpp index 3297598620..0fe0ccd887 100644 --- a/src/plugins/coreplugin/fileutils.cpp +++ b/src/plugins/coreplugin/fileutils.cpp @@ -17,7 +17,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/src/plugins/coreplugin/locator/executefilter.cpp b/src/plugins/coreplugin/locator/executefilter.cpp index 43b4d9a378..630bef03df 100644 --- a/src/plugins/coreplugin/locator/executefilter.cpp +++ b/src/plugins/coreplugin/locator/executefilter.cpp @@ -11,8 +11,8 @@ #include #include #include +#include #include -#include #include #include diff --git a/src/plugins/coreplugin/locator/spotlightlocatorfilter.cpp b/src/plugins/coreplugin/locator/spotlightlocatorfilter.cpp index 759b56fb26..587eadc615 100644 --- a/src/plugins/coreplugin/locator/spotlightlocatorfilter.cpp +++ b/src/plugins/coreplugin/locator/spotlightlocatorfilter.cpp @@ -16,8 +16,8 @@ #include #include #include +#include #include -#include #include #include diff --git a/src/plugins/coreplugin/patchtool.cpp b/src/plugins/coreplugin/patchtool.cpp index 06b20610f1..af6c11825d 100644 --- a/src/plugins/coreplugin/patchtool.cpp +++ b/src/plugins/coreplugin/patchtool.cpp @@ -7,7 +7,7 @@ #include "patchtool.h" #include -#include +#include #include diff --git a/src/plugins/coreplugin/plugininstallwizard.cpp b/src/plugins/coreplugin/plugininstallwizard.cpp index 503ab2d379..c5694016d4 100644 --- a/src/plugins/coreplugin/plugininstallwizard.cpp +++ b/src/plugins/coreplugin/plugininstallwizard.cpp @@ -16,8 +16,8 @@ #include #include #include +#include #include -#include #include #include #include diff --git a/src/plugins/coreplugin/progressmanager/processprogress.cpp b/src/plugins/coreplugin/progressmanager/processprogress.cpp index 2895b402a5..fce87e0d2b 100644 --- a/src/plugins/coreplugin/progressmanager/processprogress.cpp +++ b/src/plugins/coreplugin/progressmanager/processprogress.cpp @@ -6,8 +6,8 @@ #include "progressmanager.h" #include "../coreplugintr.h" +#include #include -#include #include diff --git a/src/plugins/cppcheck/cppcheckrunner.h b/src/plugins/cppcheck/cppcheckrunner.h index 0ec49aceb5..686a6c9eb9 100644 --- a/src/plugins/cppcheck/cppcheckrunner.h +++ b/src/plugins/cppcheck/cppcheckrunner.h @@ -4,7 +4,7 @@ #pragma once #include -#include +#include #include #include diff --git a/src/plugins/cppeditor/cppcodemodelsettings.cpp b/src/plugins/cppeditor/cppcodemodelsettings.cpp index 679b368494..5919a97b84 100644 --- a/src/plugins/cppeditor/cppcodemodelsettings.cpp +++ b/src/plugins/cppeditor/cppcodemodelsettings.cpp @@ -15,8 +15,8 @@ #include #include +#include #include -#include #include #include diff --git a/src/plugins/cppeditor/cppmodelmanager.cpp b/src/plugins/cppeditor/cppmodelmanager.cpp index 21c75b7cbc..36c3832641 100644 --- a/src/plugins/cppeditor/cppmodelmanager.cpp +++ b/src/plugins/cppeditor/cppmodelmanager.cpp @@ -63,8 +63,8 @@ #include #include #include +#include #include -#include #include #include diff --git a/src/plugins/debugger/cdb/cdbengine.cpp b/src/plugins/debugger/cdb/cdbengine.cpp index ade37ae8ec..e3a2ba8ede 100644 --- a/src/plugins/debugger/cdb/cdbengine.cpp +++ b/src/plugins/debugger/cdb/cdbengine.cpp @@ -45,9 +45,9 @@ #include #include #include +#include #include #include -#include #include #include diff --git a/src/plugins/debugger/cdb/cdbengine.h b/src/plugins/debugger/cdb/cdbengine.h index 0fba6708e9..84a0dded1a 100644 --- a/src/plugins/debugger/cdb/cdbengine.h +++ b/src/plugins/debugger/cdb/cdbengine.h @@ -10,7 +10,7 @@ #include -#include +#include #include diff --git a/src/plugins/debugger/dap/dapengine.cpp b/src/plugins/debugger/dap/dapengine.cpp index ed0933008e..9db7c0f7e5 100644 --- a/src/plugins/debugger/dap/dapengine.cpp +++ b/src/plugins/debugger/dap/dapengine.cpp @@ -22,8 +22,8 @@ #include #include +#include #include -#include #include #include diff --git a/src/plugins/debugger/dap/dapengine.h b/src/plugins/debugger/dap/dapengine.h index 9b554d668b..2fa3019cad 100644 --- a/src/plugins/debugger/dap/dapengine.h +++ b/src/plugins/debugger/dap/dapengine.h @@ -4,7 +4,7 @@ #pragma once #include -#include +#include #include diff --git a/src/plugins/debugger/debuggerengine.cpp b/src/plugins/debugger/debuggerengine.cpp index d387ce142c..a59e48ecf9 100644 --- a/src/plugins/debugger/debuggerengine.cpp +++ b/src/plugins/debugger/debuggerengine.cpp @@ -54,10 +54,10 @@ #include #include #include +#include #include #include #include -#include #include #include diff --git a/src/plugins/debugger/debuggeritem.cpp b/src/plugins/debugger/debuggeritem.cpp index 76630f2e7d..241ac32ecd 100644 --- a/src/plugins/debugger/debuggeritem.cpp +++ b/src/plugins/debugger/debuggeritem.cpp @@ -12,8 +12,8 @@ #include #include #include +#include #include -#include #include #include #include diff --git a/src/plugins/debugger/debuggeritemmanager.cpp b/src/plugins/debugger/debuggeritemmanager.cpp index f418ace88e..42f9af0800 100644 --- a/src/plugins/debugger/debuggeritemmanager.cpp +++ b/src/plugins/debugger/debuggeritemmanager.cpp @@ -22,8 +22,8 @@ #include #include #include +#include #include -#include #include #include diff --git a/src/plugins/debugger/debuggerruncontrol.cpp b/src/plugins/debugger/debuggerruncontrol.cpp index 5e5da91df6..663ad5bf6d 100644 --- a/src/plugins/debugger/debuggerruncontrol.cpp +++ b/src/plugins/debugger/debuggerruncontrol.cpp @@ -35,8 +35,8 @@ #include #include #include +#include #include -#include #include #include #include diff --git a/src/plugins/debugger/debuggersourcepathmappingwidget.cpp b/src/plugins/debugger/debuggersourcepathmappingwidget.cpp index db5d8698de..9d3af533bc 100644 --- a/src/plugins/debugger/debuggersourcepathmappingwidget.cpp +++ b/src/plugins/debugger/debuggersourcepathmappingwidget.cpp @@ -12,8 +12,8 @@ #include #include #include +#include #include -#include #include #include diff --git a/src/plugins/debugger/gdb/gdbengine.cpp b/src/plugins/debugger/gdb/gdbengine.cpp index 6068294e40..5ea6162a64 100644 --- a/src/plugins/debugger/gdb/gdbengine.cpp +++ b/src/plugins/debugger/gdb/gdbengine.cpp @@ -38,9 +38,9 @@ #include #include #include +#include #include #include -#include #include #include diff --git a/src/plugins/debugger/gdb/gdbengine.h b/src/plugins/debugger/gdb/gdbengine.h index 6a6e68991b..64a2eddd4e 100644 --- a/src/plugins/debugger/gdb/gdbengine.h +++ b/src/plugins/debugger/gdb/gdbengine.h @@ -15,7 +15,7 @@ #include #include -#include +#include #include #include diff --git a/src/plugins/debugger/lldb/lldbengine.cpp b/src/plugins/debugger/lldb/lldbengine.cpp index 91ef914c55..3f182c828b 100644 --- a/src/plugins/debugger/lldb/lldbengine.cpp +++ b/src/plugins/debugger/lldb/lldbengine.cpp @@ -29,9 +29,9 @@ #include #include +#include #include #include -#include #include #include diff --git a/src/plugins/debugger/lldb/lldbengine.h b/src/plugins/debugger/lldb/lldbengine.h index 2f5fe0d768..db11af9c10 100644 --- a/src/plugins/debugger/lldb/lldbengine.h +++ b/src/plugins/debugger/lldb/lldbengine.h @@ -11,7 +11,7 @@ #include #include -#include +#include #include #include diff --git a/src/plugins/debugger/moduleshandler.cpp b/src/plugins/debugger/moduleshandler.cpp index a904e1d789..4f063b5728 100644 --- a/src/plugins/debugger/moduleshandler.cpp +++ b/src/plugins/debugger/moduleshandler.cpp @@ -11,8 +11,8 @@ #include #include +#include #include -#include #include #include diff --git a/src/plugins/debugger/pdb/pdbengine.cpp b/src/plugins/debugger/pdb/pdbengine.cpp index 54a347fb15..accf32d0e6 100644 --- a/src/plugins/debugger/pdb/pdbengine.cpp +++ b/src/plugins/debugger/pdb/pdbengine.cpp @@ -22,8 +22,8 @@ #include #include +#include #include -#include #include #include diff --git a/src/plugins/debugger/pdb/pdbengine.h b/src/plugins/debugger/pdb/pdbengine.h index 49dceb2441..1e365b36a7 100644 --- a/src/plugins/debugger/pdb/pdbengine.h +++ b/src/plugins/debugger/pdb/pdbengine.h @@ -4,7 +4,7 @@ #pragma once #include -#include +#include #include diff --git a/src/plugins/debugger/qml/qmlengine.cpp b/src/plugins/debugger/qml/qmlengine.cpp index 096ddc1326..033069c116 100644 --- a/src/plugins/debugger/qml/qmlengine.cpp +++ b/src/plugins/debugger/qml/qmlengine.cpp @@ -40,8 +40,8 @@ #include #include +#include #include -#include #include #include diff --git a/src/plugins/debugger/terminal.cpp b/src/plugins/debugger/terminal.cpp index 4b96d1a0a9..cc309541a8 100644 --- a/src/plugins/debugger/terminal.cpp +++ b/src/plugins/debugger/terminal.cpp @@ -11,8 +11,8 @@ #include #include +#include #include -#include #include #include diff --git a/src/plugins/docker/dockerapi.cpp b/src/plugins/docker/dockerapi.cpp index 3ffa59b52b..ffc1414859 100644 --- a/src/plugins/docker/dockerapi.cpp +++ b/src/plugins/docker/dockerapi.cpp @@ -7,8 +7,8 @@ #include #include +#include #include -#include #include diff --git a/src/plugins/docker/dockerdevice.cpp b/src/plugins/docker/dockerdevice.cpp index 64d3dcd6da..d1175a8b5f 100644 --- a/src/plugins/docker/dockerdevice.cpp +++ b/src/plugins/docker/dockerdevice.cpp @@ -44,9 +44,9 @@ #include #include #include +#include #include #include -#include #include #include #include diff --git a/src/plugins/fakevim/fakevimplugin.cpp b/src/plugins/fakevim/fakevimplugin.cpp index b13ff9dfce..347e3a2b7b 100644 --- a/src/plugins/fakevim/fakevimplugin.cpp +++ b/src/plugins/fakevim/fakevimplugin.cpp @@ -50,8 +50,8 @@ #include #include #include +#include #include -#include #include #include diff --git a/src/plugins/fossil/fossilclient.cpp b/src/plugins/fossil/fossilclient.cpp index 16038150cb..358a66caaf 100644 --- a/src/plugins/fossil/fossilclient.cpp +++ b/src/plugins/fossil/fossilclient.cpp @@ -16,9 +16,9 @@ #include #include #include +#include #include #include -#include #include #include diff --git a/src/plugins/genericprojectmanager/genericproject.cpp b/src/plugins/genericprojectmanager/genericproject.cpp index 5553e0a740..906eeb5809 100644 --- a/src/plugins/genericprojectmanager/genericproject.cpp +++ b/src/plugins/genericprojectmanager/genericproject.cpp @@ -38,8 +38,8 @@ #include #include #include +#include #include -#include #include #include diff --git a/src/plugins/git/branchmodel.cpp b/src/plugins/git/branchmodel.cpp index 275b00efbb..aeeea39fff 100644 --- a/src/plugins/git/branchmodel.cpp +++ b/src/plugins/git/branchmodel.cpp @@ -11,8 +11,8 @@ #include #include +#include #include -#include #include #include diff --git a/src/plugins/git/changeselectiondialog.cpp b/src/plugins/git/changeselectiondialog.cpp index 2f93a2c7a1..8e4a6bdc99 100644 --- a/src/plugins/git/changeselectiondialog.cpp +++ b/src/plugins/git/changeselectiondialog.cpp @@ -12,7 +12,7 @@ #include #include #include -#include +#include #include #include diff --git a/src/plugins/git/gerrit/gerritmodel.cpp b/src/plugins/git/gerrit/gerritmodel.cpp index 4791a41d4f..6457117b32 100644 --- a/src/plugins/git/gerrit/gerritmodel.cpp +++ b/src/plugins/git/gerrit/gerritmodel.cpp @@ -10,8 +10,8 @@ #include #include +#include #include -#include #include #include diff --git a/src/plugins/git/gerrit/gerritplugin.cpp b/src/plugins/git/gerrit/gerritplugin.cpp index 0f5a393b1d..8ffc7a6d44 100644 --- a/src/plugins/git/gerrit/gerritplugin.cpp +++ b/src/plugins/git/gerrit/gerritplugin.cpp @@ -22,8 +22,8 @@ #include #include +#include #include -#include #include diff --git a/src/plugins/git/gitclient.cpp b/src/plugins/git/gitclient.cpp index ab5c8cc58a..a196d703ed 100644 --- a/src/plugins/git/gitclient.cpp +++ b/src/plugins/git/gitclient.cpp @@ -27,8 +27,8 @@ #include #include #include +#include #include -#include #include #include diff --git a/src/plugins/git/gitclient.h b/src/plugins/git/gitclient.h index 0c4e412625..a52276f381 100644 --- a/src/plugins/git/gitclient.h +++ b/src/plugins/git/gitclient.h @@ -13,7 +13,7 @@ #include #include -#include +#include #include #include diff --git a/src/plugins/git/gitgrep.cpp b/src/plugins/git/gitgrep.cpp index 2f70cddc82..edd042c9b9 100644 --- a/src/plugins/git/gitgrep.cpp +++ b/src/plugins/git/gitgrep.cpp @@ -17,8 +17,8 @@ #include #include #include +#include #include -#include #include #include diff --git a/src/plugins/git/mergetool.h b/src/plugins/git/mergetool.h index 1fd32e3a4f..727f9a85df 100644 --- a/src/plugins/git/mergetool.h +++ b/src/plugins/git/mergetool.h @@ -3,7 +3,7 @@ #pragma once -#include +#include #include #include diff --git a/src/plugins/gitlab/gitlabclonedialog.cpp b/src/plugins/gitlab/gitlabclonedialog.cpp index 4d54105e44..3a061b9cc5 100644 --- a/src/plugins/gitlab/gitlabclonedialog.cpp +++ b/src/plugins/gitlab/gitlabclonedialog.cpp @@ -23,8 +23,8 @@ #include #include #include +#include #include -#include #include #include diff --git a/src/plugins/gitlab/queryrunner.h b/src/plugins/gitlab/queryrunner.h index bdb5e06034..08afc56e1b 100644 --- a/src/plugins/gitlab/queryrunner.h +++ b/src/plugins/gitlab/queryrunner.h @@ -4,7 +4,7 @@ #pragma once #include -#include +#include #include diff --git a/src/plugins/haskell/haskellmanager.cpp b/src/plugins/haskell/haskellmanager.cpp index 250b795af7..fbd4ee8aa0 100644 --- a/src/plugins/haskell/haskellmanager.cpp +++ b/src/plugins/haskell/haskellmanager.cpp @@ -10,8 +10,8 @@ #include #include #include +#include #include -#include #include #include diff --git a/src/plugins/incredibuild/cmakecommandbuilder.cpp b/src/plugins/incredibuild/cmakecommandbuilder.cpp index 8732601cbc..2f0dd751ae 100644 --- a/src/plugins/incredibuild/cmakecommandbuilder.cpp +++ b/src/plugins/incredibuild/cmakecommandbuilder.cpp @@ -8,7 +8,7 @@ #include #include -#include +#include #include // Compile-time only diff --git a/src/plugins/ios/iosbuildstep.cpp b/src/plugins/ios/iosbuildstep.cpp index e4771d97e8..7831d84e23 100644 --- a/src/plugins/ios/iosbuildstep.cpp +++ b/src/plugins/ios/iosbuildstep.cpp @@ -20,8 +20,8 @@ #include #include +#include #include -#include #include #include diff --git a/src/plugins/ios/iosconfigurations.cpp b/src/plugins/ios/iosconfigurations.cpp index 0eab6b7947..04e4363a2a 100644 --- a/src/plugins/ios/iosconfigurations.cpp +++ b/src/plugins/ios/iosconfigurations.cpp @@ -31,8 +31,8 @@ #include #include +#include #include -#include #include #include diff --git a/src/plugins/ios/iosdsymbuildstep.cpp b/src/plugins/ios/iosdsymbuildstep.cpp index 33ff0e7e20..2d0e2b841f 100644 --- a/src/plugins/ios/iosdsymbuildstep.cpp +++ b/src/plugins/ios/iosdsymbuildstep.cpp @@ -9,21 +9,22 @@ #include "iostr.h" #include -#include -#include + +#include #include #include #include +#include #include -#include #include +#include #include #include -#include +#include #include -#include +#include #include #include diff --git a/src/plugins/ios/iosprobe.cpp b/src/plugins/ios/iosprobe.cpp index 7b3e977e96..e6fca977b2 100644 --- a/src/plugins/ios/iosprobe.cpp +++ b/src/plugins/ios/iosprobe.cpp @@ -4,7 +4,7 @@ #include "iosprobe.h" #include -#include +#include #include #include diff --git a/src/plugins/ios/iosrunconfiguration.cpp b/src/plugins/ios/iosrunconfiguration.cpp index 5c9170f2ba..8a0a3e62dc 100644 --- a/src/plugins/ios/iosrunconfiguration.cpp +++ b/src/plugins/ios/iosrunconfiguration.cpp @@ -21,9 +21,9 @@ #include #include -#include -#include #include +#include +#include #include #include diff --git a/src/plugins/ios/iosrunner.cpp b/src/plugins/ios/iosrunner.cpp index c01c3c859d..828bb65c00 100644 --- a/src/plugins/ios/iosrunner.cpp +++ b/src/plugins/ios/iosrunner.cpp @@ -27,7 +27,7 @@ #include #include -#include +#include #include #include diff --git a/src/plugins/ios/iossimulator.cpp b/src/plugins/ios/iossimulator.cpp index 2caa691c92..fa68c4031e 100644 --- a/src/plugins/ios/iossimulator.cpp +++ b/src/plugins/ios/iossimulator.cpp @@ -8,7 +8,7 @@ #include #include -#include +#include #include diff --git a/src/plugins/ios/iostoolhandler.cpp b/src/plugins/ios/iostoolhandler.cpp index fa5d0c3ac4..0e4545bf1d 100644 --- a/src/plugins/ios/iostoolhandler.cpp +++ b/src/plugins/ios/iostoolhandler.cpp @@ -15,8 +15,8 @@ #include #include #include +#include #include -#include #include #include diff --git a/src/plugins/ios/simulatorcontrol.cpp b/src/plugins/ios/simulatorcontrol.cpp index 9d50088cd9..0832a5faf3 100644 --- a/src/plugins/ios/simulatorcontrol.cpp +++ b/src/plugins/ios/simulatorcontrol.cpp @@ -6,8 +6,8 @@ #include #include +#include #include -#include #ifdef Q_OS_MAC #include diff --git a/src/plugins/languageclient/client.cpp b/src/plugins/languageclient/client.cpp index 08d7429acd..77b2cbfdee 100644 --- a/src/plugins/languageclient/client.cpp +++ b/src/plugins/languageclient/client.cpp @@ -53,7 +53,7 @@ #include #include -#include +#include #include #include diff --git a/src/plugins/languageclient/languageclientinterface.h b/src/plugins/languageclient/languageclientinterface.h index ec1fc8206f..7577f13691 100644 --- a/src/plugins/languageclient/languageclientinterface.h +++ b/src/plugins/languageclient/languageclientinterface.h @@ -8,7 +8,7 @@ #include #include -#include +#include #include #include diff --git a/src/plugins/mcusupport/mcuqmlprojectnode.h b/src/plugins/mcusupport/mcuqmlprojectnode.h index 2a06e5cde5..bf40a696f6 100644 --- a/src/plugins/mcusupport/mcuqmlprojectnode.h +++ b/src/plugins/mcusupport/mcuqmlprojectnode.h @@ -9,7 +9,7 @@ #include #include -#include +#include #include #include diff --git a/src/plugins/mcusupport/mcusupportversiondetection.cpp b/src/plugins/mcusupport/mcusupportversiondetection.cpp index 2ea28c3852..f92a443c4f 100644 --- a/src/plugins/mcusupport/mcusupportversiondetection.cpp +++ b/src/plugins/mcusupport/mcusupportversiondetection.cpp @@ -3,7 +3,7 @@ #include "mcusupportversiondetection.h" -#include +#include #include #include diff --git a/src/plugins/mercurial/mercurialclient.cpp b/src/plugins/mercurial/mercurialclient.cpp index 6243989650..1d8d542ed9 100644 --- a/src/plugins/mercurial/mercurialclient.cpp +++ b/src/plugins/mercurial/mercurialclient.cpp @@ -12,8 +12,8 @@ #include #include #include +#include #include -#include #include #include diff --git a/src/plugins/mesonprojectmanager/mesonbuildconfiguration.cpp b/src/plugins/mesonprojectmanager/mesonbuildconfiguration.cpp index bd90ee818c..514c529212 100644 --- a/src/plugins/mesonprojectmanager/mesonbuildconfiguration.cpp +++ b/src/plugins/mesonprojectmanager/mesonbuildconfiguration.cpp @@ -19,7 +19,7 @@ #include #include -#include +#include #include diff --git a/src/plugins/mesonprojectmanager/mesonprocess.cpp b/src/plugins/mesonprojectmanager/mesonprocess.cpp index 5732f617e7..2e4ba02455 100644 --- a/src/plugins/mesonprojectmanager/mesonprocess.cpp +++ b/src/plugins/mesonprojectmanager/mesonprocess.cpp @@ -13,7 +13,7 @@ #include #include -#include +#include #include #include diff --git a/src/plugins/mesonprojectmanager/mesonwrapper.h b/src/plugins/mesonprojectmanager/mesonwrapper.h index 668c78bc4c..6ec1e57a0f 100644 --- a/src/plugins/mesonprojectmanager/mesonwrapper.h +++ b/src/plugins/mesonprojectmanager/mesonwrapper.h @@ -9,7 +9,7 @@ #include #include #include -#include +#include #include #include diff --git a/src/plugins/mesonprojectmanager/toolwrapper.cpp b/src/plugins/mesonprojectmanager/toolwrapper.cpp index e3e54ef1b2..83ed27f495 100644 --- a/src/plugins/mesonprojectmanager/toolwrapper.cpp +++ b/src/plugins/mesonprojectmanager/toolwrapper.cpp @@ -3,7 +3,7 @@ #include "toolwrapper.h" -#include +#include namespace MesonProjectManager { namespace Internal { diff --git a/src/plugins/nim/project/nimblebuildsystem.cpp b/src/plugins/nim/project/nimblebuildsystem.cpp index f9be804571..3a8ccb08d6 100644 --- a/src/plugins/nim/project/nimblebuildsystem.cpp +++ b/src/plugins/nim/project/nimblebuildsystem.cpp @@ -10,8 +10,8 @@ #include #include +#include #include -#include using namespace ProjectExplorer; using namespace Utils; diff --git a/src/plugins/nim/project/nimcompilerbuildstep.cpp b/src/plugins/nim/project/nimcompilerbuildstep.cpp index 87f93e53e2..588098619a 100644 --- a/src/plugins/nim/project/nimcompilerbuildstep.cpp +++ b/src/plugins/nim/project/nimcompilerbuildstep.cpp @@ -16,8 +16,8 @@ #include #include +#include #include -#include #include #include diff --git a/src/plugins/nim/project/nimtoolchain.cpp b/src/plugins/nim/project/nimtoolchain.cpp index 159985f59d..21b441fa6c 100644 --- a/src/plugins/nim/project/nimtoolchain.cpp +++ b/src/plugins/nim/project/nimtoolchain.cpp @@ -9,7 +9,7 @@ #include #include -#include +#include #include diff --git a/src/plugins/nim/suggest/server.h b/src/plugins/nim/suggest/server.h index a9f7d49b88..9eb2bac141 100644 --- a/src/plugins/nim/suggest/server.h +++ b/src/plugins/nim/suggest/server.h @@ -7,7 +7,7 @@ #include #include -#include +#include namespace Nim { namespace Suggest { diff --git a/src/plugins/perforce/perforcechecker.h b/src/plugins/perforce/perforcechecker.h index 5f7d2b1673..d0f608de70 100644 --- a/src/plugins/perforce/perforcechecker.h +++ b/src/plugins/perforce/perforcechecker.h @@ -4,7 +4,7 @@ #pragma once #include -#include +#include namespace Perforce::Internal { diff --git a/src/plugins/perforce/perforceplugin.cpp b/src/plugins/perforce/perforceplugin.cpp index 336ee8e7dc..c6f4082767 100644 --- a/src/plugins/perforce/perforceplugin.cpp +++ b/src/plugins/perforce/perforceplugin.cpp @@ -27,8 +27,8 @@ #include #include #include +#include #include -#include #include #include diff --git a/src/plugins/perfprofiler/perfconfigwidget.cpp b/src/plugins/perfprofiler/perfconfigwidget.cpp index eed31e373a..e5e3fd3725 100644 --- a/src/plugins/perfprofiler/perfconfigwidget.cpp +++ b/src/plugins/perfprofiler/perfconfigwidget.cpp @@ -14,8 +14,8 @@ #include #include +#include #include -#include #include #include diff --git a/src/plugins/perfprofiler/perfprofilerruncontrol.cpp b/src/plugins/perfprofiler/perfprofilerruncontrol.cpp index 68ba9e883f..8579a9cf7c 100644 --- a/src/plugins/perfprofiler/perfprofilerruncontrol.cpp +++ b/src/plugins/perfprofiler/perfprofilerruncontrol.cpp @@ -17,7 +17,7 @@ #include #include -#include +#include #include #include diff --git a/src/plugins/perfprofiler/perfsettings.cpp b/src/plugins/perfprofiler/perfsettings.cpp index 9bea76b3e2..e5f307b85a 100644 --- a/src/plugins/perfprofiler/perfsettings.cpp +++ b/src/plugins/perfprofiler/perfsettings.cpp @@ -10,7 +10,7 @@ #include -#include +#include using namespace Utils; diff --git a/src/plugins/perfprofiler/perftracepointdialog.cpp b/src/plugins/perfprofiler/perftracepointdialog.cpp index 004f9aa0e1..3920b526b8 100644 --- a/src/plugins/perfprofiler/perftracepointdialog.cpp +++ b/src/plugins/perfprofiler/perftracepointdialog.cpp @@ -11,9 +11,9 @@ #include #include -#include -#include #include +#include +#include #include #include diff --git a/src/plugins/projectexplorer/abstractprocessstep.cpp b/src/plugins/projectexplorer/abstractprocessstep.cpp index eca8b5c44f..ddc2a8551a 100644 --- a/src/plugins/projectexplorer/abstractprocessstep.cpp +++ b/src/plugins/projectexplorer/abstractprocessstep.cpp @@ -12,8 +12,8 @@ #include #include +#include #include -#include #include diff --git a/src/plugins/projectexplorer/customwizard/customwizardscriptgenerator.cpp b/src/plugins/projectexplorer/customwizard/customwizardscriptgenerator.cpp index 34ab30442d..7d1174839d 100644 --- a/src/plugins/projectexplorer/customwizard/customwizardscriptgenerator.cpp +++ b/src/plugins/projectexplorer/customwizard/customwizardscriptgenerator.cpp @@ -8,7 +8,7 @@ #include #include #include -#include +#include #include #include diff --git a/src/plugins/projectexplorer/devicesupport/desktopdevice.cpp b/src/plugins/projectexplorer/devicesupport/desktopdevice.cpp index 82734cf6a9..26d296b181 100644 --- a/src/plugins/projectexplorer/devicesupport/desktopdevice.cpp +++ b/src/plugins/projectexplorer/devicesupport/desktopdevice.cpp @@ -15,8 +15,8 @@ #include #include #include +#include #include -#include #include #include #include diff --git a/src/plugins/projectexplorer/devicesupport/devicemanager.cpp b/src/plugins/projectexplorer/devicesupport/devicemanager.cpp index 8973a7baf6..aa017df46b 100644 --- a/src/plugins/projectexplorer/devicesupport/devicemanager.cpp +++ b/src/plugins/projectexplorer/devicesupport/devicemanager.cpp @@ -14,8 +14,8 @@ #include #include #include +#include #include -#include #include #include diff --git a/src/plugins/projectexplorer/devicesupport/deviceusedportsgatherer.cpp b/src/plugins/projectexplorer/devicesupport/deviceusedportsgatherer.cpp index b04397a66b..fbe300bf26 100644 --- a/src/plugins/projectexplorer/devicesupport/deviceusedportsgatherer.cpp +++ b/src/plugins/projectexplorer/devicesupport/deviceusedportsgatherer.cpp @@ -9,8 +9,8 @@ #include #include +#include #include -#include #include #include diff --git a/src/plugins/projectexplorer/devicesupport/sshparameters.cpp b/src/plugins/projectexplorer/devicesupport/sshparameters.cpp index 8b67f300db..744e350eae 100644 --- a/src/plugins/projectexplorer/devicesupport/sshparameters.cpp +++ b/src/plugins/projectexplorer/devicesupport/sshparameters.cpp @@ -8,8 +8,8 @@ #include #include #include +#include #include -#include #include diff --git a/src/plugins/projectexplorer/extracompiler.cpp b/src/plugins/projectexplorer/extracompiler.cpp index e60d6cb5d1..8830aadf85 100644 --- a/src/plugins/projectexplorer/extracompiler.cpp +++ b/src/plugins/projectexplorer/extracompiler.cpp @@ -16,7 +16,7 @@ #include #include #include -#include +#include #include #include diff --git a/src/plugins/projectexplorer/gcctoolchain.cpp b/src/plugins/projectexplorer/gcctoolchain.cpp index 40a97737db..4012fbd669 100644 --- a/src/plugins/projectexplorer/gcctoolchain.cpp +++ b/src/plugins/projectexplorer/gcctoolchain.cpp @@ -20,8 +20,8 @@ #include #include #include +#include #include -#include #include #include diff --git a/src/plugins/projectexplorer/makestep.cpp b/src/plugins/projectexplorer/makestep.cpp index 9a3a939f34..b3b9c93486 100644 --- a/src/plugins/projectexplorer/makestep.cpp +++ b/src/plugins/projectexplorer/makestep.cpp @@ -18,7 +18,7 @@ #include #include #include -#include +#include #include #include diff --git a/src/plugins/projectexplorer/msvctoolchain.cpp b/src/plugins/projectexplorer/msvctoolchain.cpp index 87547b2a79..d4d518de44 100644 --- a/src/plugins/projectexplorer/msvctoolchain.cpp +++ b/src/plugins/projectexplorer/msvctoolchain.cpp @@ -19,8 +19,8 @@ #include #include #include +#include #include -#include #include #include diff --git a/src/plugins/projectexplorer/processparameters.cpp b/src/plugins/projectexplorer/processparameters.cpp index 49b50dccb3..0b3d6d83c7 100644 --- a/src/plugins/projectexplorer/processparameters.cpp +++ b/src/plugins/projectexplorer/processparameters.cpp @@ -5,7 +5,7 @@ #include #include -#include +#include #include #include diff --git a/src/plugins/projectexplorer/projectmodels.cpp b/src/plugins/projectexplorer/projectmodels.cpp index d318de8cc3..bc5a0ef4d6 100644 --- a/src/plugins/projectexplorer/projectmodels.cpp +++ b/src/plugins/projectexplorer/projectmodels.cpp @@ -25,8 +25,8 @@ #include #include #include +#include #include -#include #include #include diff --git a/src/plugins/projectexplorer/runconfigurationaspects.cpp b/src/plugins/projectexplorer/runconfigurationaspects.cpp index d90fbc7272..88dd720ee3 100644 --- a/src/plugins/projectexplorer/runconfigurationaspects.cpp +++ b/src/plugins/projectexplorer/runconfigurationaspects.cpp @@ -19,8 +19,8 @@ #include #include #include +#include #include -#include #include #include diff --git a/src/plugins/projectexplorer/runcontrol.cpp b/src/plugins/projectexplorer/runcontrol.cpp index 3f0accdc31..3843e4c0e5 100644 --- a/src/plugins/projectexplorer/runcontrol.cpp +++ b/src/plugins/projectexplorer/runcontrol.cpp @@ -25,9 +25,9 @@ #include #include #include +#include #include #include -#include #include #include diff --git a/src/plugins/projectexplorer/targetsetuppage.cpp b/src/plugins/projectexplorer/targetsetuppage.cpp index 3b11c8f147..fd1e8a78c6 100644 --- a/src/plugins/projectexplorer/targetsetuppage.cpp +++ b/src/plugins/projectexplorer/targetsetuppage.cpp @@ -11,18 +11,17 @@ #include "project.h" #include "projectexplorerconstants.h" #include "projectexplorertr.h" -#include "session.h" #include "target.h" #include "targetsetupwidget.h" #include "task.h" #include -#include -#include -#include #include #include +#include +#include +#include #include #include diff --git a/src/plugins/projectexplorer/taskfile.cpp b/src/plugins/projectexplorer/taskfile.cpp index 6375d12ee7..f137b0f812 100644 --- a/src/plugins/projectexplorer/taskfile.cpp +++ b/src/plugins/projectexplorer/taskfile.cpp @@ -14,8 +14,8 @@ #include #include +#include #include -#include #include #include diff --git a/src/plugins/projectexplorer/toolchainconfigwidget.cpp b/src/plugins/projectexplorer/toolchainconfigwidget.cpp index ef97ad72cf..84b80b4e04 100644 --- a/src/plugins/projectexplorer/toolchainconfigwidget.cpp +++ b/src/plugins/projectexplorer/toolchainconfigwidget.cpp @@ -7,8 +7,8 @@ #include "projectexplorertr.h" #include +#include #include -#include #include #include diff --git a/src/plugins/projectexplorer/userfileaccessor.cpp b/src/plugins/projectexplorer/userfileaccessor.cpp index 646e336643..ae900ea818 100644 --- a/src/plugins/projectexplorer/userfileaccessor.cpp +++ b/src/plugins/projectexplorer/userfileaccessor.cpp @@ -18,8 +18,8 @@ #include #include #include +#include #include -#include #include diff --git a/src/plugins/python/pipsupport.cpp b/src/plugins/python/pipsupport.cpp index db45647945..8e3f55dd11 100644 --- a/src/plugins/python/pipsupport.cpp +++ b/src/plugins/python/pipsupport.cpp @@ -16,7 +16,7 @@ #include #include #include -#include +#include using namespace Utils; diff --git a/src/plugins/python/pipsupport.h b/src/plugins/python/pipsupport.h index fefd329575..4d08a3b1ea 100644 --- a/src/plugins/python/pipsupport.h +++ b/src/plugins/python/pipsupport.h @@ -4,7 +4,7 @@ #pragma once #include -#include +#include #include #include diff --git a/src/plugins/python/pyside.cpp b/src/plugins/python/pyside.cpp index eb604f01e6..4b9df185a3 100644 --- a/src/plugins/python/pyside.cpp +++ b/src/plugins/python/pyside.cpp @@ -5,7 +5,6 @@ #include "pipsupport.h" #include "pythonplugin.h" -#include "pythonsettings.h" #include "pythontr.h" #include "pythonutils.h" @@ -19,8 +18,8 @@ #include #include #include +#include #include -#include #include #include diff --git a/src/plugins/python/pysideuicextracompiler.cpp b/src/plugins/python/pysideuicextracompiler.cpp index c195aeaa1f..45fb68066f 100644 --- a/src/plugins/python/pysideuicextracompiler.cpp +++ b/src/plugins/python/pysideuicextracompiler.cpp @@ -3,7 +3,7 @@ #include "pysideuicextracompiler.h" -#include +#include using namespace ProjectExplorer; using namespace Utils; diff --git a/src/plugins/python/pythonlanguageclient.cpp b/src/plugins/python/pythonlanguageclient.cpp index 6d3d7c8cfa..9f347d8e48 100644 --- a/src/plugins/python/pythonlanguageclient.cpp +++ b/src/plugins/python/pythonlanguageclient.cpp @@ -31,7 +31,7 @@ #include #include -#include +#include #include #include diff --git a/src/plugins/python/pythonsettings.cpp b/src/plugins/python/pythonsettings.cpp index 119bd9d260..e5251384d2 100644 --- a/src/plugins/python/pythonsettings.cpp +++ b/src/plugins/python/pythonsettings.cpp @@ -27,7 +27,7 @@ #include #include #include -#include +#include #include #include diff --git a/src/plugins/python/pythonutils.cpp b/src/plugins/python/pythonutils.cpp index 328ada95d9..0fb4d03f19 100644 --- a/src/plugins/python/pythonutils.cpp +++ b/src/plugins/python/pythonutils.cpp @@ -16,7 +16,7 @@ #include #include -#include +#include using namespace ProjectExplorer; using namespace Utils; diff --git a/src/plugins/qbsprojectmanager/qbsbuildconfiguration.cpp b/src/plugins/qbsprojectmanager/qbsbuildconfiguration.cpp index c5d4b62a0d..41ae75d8b9 100644 --- a/src/plugins/qbsprojectmanager/qbsbuildconfiguration.cpp +++ b/src/plugins/qbsprojectmanager/qbsbuildconfiguration.cpp @@ -27,8 +27,8 @@ #include +#include #include -#include #include #include diff --git a/src/plugins/qbsprojectmanager/qbsbuildstep.cpp b/src/plugins/qbsprojectmanager/qbsbuildstep.cpp index 102cb7e3ae..794e134d5a 100644 --- a/src/plugins/qbsprojectmanager/qbsbuildstep.cpp +++ b/src/plugins/qbsprojectmanager/qbsbuildstep.cpp @@ -28,8 +28,8 @@ #include #include #include +#include #include -#include #include #include diff --git a/src/plugins/qbsprojectmanager/qbsprofilemanager.cpp b/src/plugins/qbsprojectmanager/qbsprofilemanager.cpp index 953768661d..2d952513ab 100644 --- a/src/plugins/qbsprojectmanager/qbsprofilemanager.cpp +++ b/src/plugins/qbsprojectmanager/qbsprofilemanager.cpp @@ -18,8 +18,8 @@ #include #include #include +#include #include -#include #include #include diff --git a/src/plugins/qbsprojectmanager/qbssession.cpp b/src/plugins/qbsprojectmanager/qbssession.cpp index 7248143313..ef0ef8e52e 100644 --- a/src/plugins/qbsprojectmanager/qbssession.cpp +++ b/src/plugins/qbsprojectmanager/qbssession.cpp @@ -14,8 +14,8 @@ #include #include #include +#include #include -#include #include #include diff --git a/src/plugins/qbsprojectmanager/qbssettings.cpp b/src/plugins/qbsprojectmanager/qbssettings.cpp index 6317580f68..91e4763bf2 100644 --- a/src/plugins/qbsprojectmanager/qbssettings.cpp +++ b/src/plugins/qbsprojectmanager/qbssettings.cpp @@ -12,7 +12,7 @@ #include #include #include -#include +#include #include #include diff --git a/src/plugins/qmakeprojectmanager/librarydetailscontroller.cpp b/src/plugins/qmakeprojectmanager/librarydetailscontroller.cpp index 8c094c557a..800d7350c1 100644 --- a/src/plugins/qmakeprojectmanager/librarydetailscontroller.cpp +++ b/src/plugins/qmakeprojectmanager/librarydetailscontroller.cpp @@ -13,8 +13,8 @@ #include #include +#include #include -#include #include #include diff --git a/src/plugins/qmakeprojectmanager/makefileparse.cpp b/src/plugins/qmakeprojectmanager/makefileparse.cpp index 5fbab2084d..990fd0ff41 100644 --- a/src/plugins/qmakeprojectmanager/makefileparse.cpp +++ b/src/plugins/qmakeprojectmanager/makefileparse.cpp @@ -5,7 +5,7 @@ #include -#include +#include #include #include diff --git a/src/plugins/qmakeprojectmanager/qmakebuildconfiguration.cpp b/src/plugins/qmakeprojectmanager/qmakebuildconfiguration.cpp index 779d175b80..ce64ecd2d9 100644 --- a/src/plugins/qmakeprojectmanager/qmakebuildconfiguration.cpp +++ b/src/plugins/qmakeprojectmanager/qmakebuildconfiguration.cpp @@ -37,8 +37,8 @@ #include #include +#include #include -#include #include #include diff --git a/src/plugins/qmakeprojectmanager/qmakemakestep.cpp b/src/plugins/qmakeprojectmanager/qmakemakestep.cpp index 0fdaecc3db..ae35a9dc76 100644 --- a/src/plugins/qmakeprojectmanager/qmakemakestep.cpp +++ b/src/plugins/qmakeprojectmanager/qmakemakestep.cpp @@ -22,7 +22,7 @@ #include #include -#include +#include #include #include diff --git a/src/plugins/qmakeprojectmanager/qmakeparsernodes.cpp b/src/plugins/qmakeprojectmanager/qmakeparsernodes.cpp index 4786d2f07a..31a55faab0 100644 --- a/src/plugins/qmakeprojectmanager/qmakeparsernodes.cpp +++ b/src/plugins/qmakeprojectmanager/qmakeparsernodes.cpp @@ -33,8 +33,8 @@ #include #include #include +#include #include -#include #include #include diff --git a/src/plugins/qmakeprojectmanager/qmakeproject.cpp b/src/plugins/qmakeprojectmanager/qmakeproject.cpp index a78c001283..2b73c154f6 100644 --- a/src/plugins/qmakeprojectmanager/qmakeproject.cpp +++ b/src/plugins/qmakeprojectmanager/qmakeproject.cpp @@ -49,7 +49,7 @@ #include #include -#include +#include #include #include diff --git a/src/plugins/qmakeprojectmanager/qmakeprojectimporter.cpp b/src/plugins/qmakeprojectmanager/qmakeprojectimporter.cpp index 8bcbe2027c..1a929bf9a4 100644 --- a/src/plugins/qmakeprojectmanager/qmakeprojectimporter.cpp +++ b/src/plugins/qmakeprojectmanager/qmakeprojectimporter.cpp @@ -23,8 +23,8 @@ #include #include +#include #include -#include #include #include diff --git a/src/plugins/qmakeprojectmanager/qmakestep.cpp b/src/plugins/qmakeprojectmanager/qmakestep.cpp index d8e99a39a5..edcc0e40bb 100644 --- a/src/plugins/qmakeprojectmanager/qmakestep.cpp +++ b/src/plugins/qmakeprojectmanager/qmakestep.cpp @@ -36,7 +36,7 @@ #include #include #include -#include +#include #include #include diff --git a/src/plugins/qmldesigner/components/componentcore/modelnodeoperations.cpp b/src/plugins/qmldesigner/components/componentcore/modelnodeoperations.cpp index f6ea4a8455..10386425fe 100644 --- a/src/plugins/qmldesigner/components/componentcore/modelnodeoperations.cpp +++ b/src/plugins/qmldesigner/components/componentcore/modelnodeoperations.cpp @@ -55,8 +55,8 @@ #include #include +#include #include -#include "utils/qtcprocess.h" #include #include diff --git a/src/plugins/qmldesigner/designercore/instances/nodeinstanceview.cpp b/src/plugins/qmldesigner/designercore/instances/nodeinstanceview.cpp index 67674ed5e9..8ebfaf5204 100644 --- a/src/plugins/qmldesigner/designercore/instances/nodeinstanceview.cpp +++ b/src/plugins/qmldesigner/designercore/instances/nodeinstanceview.cpp @@ -75,8 +75,8 @@ #include #include +#include #include -#include #include #include diff --git a/src/plugins/qmldesigner/generateresource.cpp b/src/plugins/qmldesigner/generateresource.cpp index 673ba41de4..439e124b70 100644 --- a/src/plugins/qmldesigner/generateresource.cpp +++ b/src/plugins/qmldesigner/generateresource.cpp @@ -22,9 +22,9 @@ #include #include +#include #include #include -#include #include #include diff --git a/src/plugins/qmlpreview/qmlpreviewruncontrol.cpp b/src/plugins/qmlpreview/qmlpreviewruncontrol.cpp index 6b886389e6..ca43b07a42 100644 --- a/src/plugins/qmlpreview/qmlpreviewruncontrol.cpp +++ b/src/plugins/qmlpreview/qmlpreviewruncontrol.cpp @@ -18,7 +18,7 @@ #include #include -#include +#include #include using namespace ProjectExplorer; diff --git a/src/plugins/qmlprofiler/qmlprofilerruncontrol.cpp b/src/plugins/qmlprofiler/qmlprofilerruncontrol.cpp index f5c45789d8..41b67edda7 100644 --- a/src/plugins/qmlprofiler/qmlprofilerruncontrol.cpp +++ b/src/plugins/qmlprofiler/qmlprofilerruncontrol.cpp @@ -20,8 +20,8 @@ #include +#include #include -#include #include #include diff --git a/src/plugins/qmlprojectmanager/qmlproject.cpp b/src/plugins/qmlprojectmanager/qmlproject.cpp index aab0fcfe1c..77e3cc82d4 100644 --- a/src/plugins/qmlprojectmanager/qmlproject.cpp +++ b/src/plugins/qmlprojectmanager/qmlproject.cpp @@ -38,8 +38,8 @@ #include #include +#include #include -#include #include #include diff --git a/src/plugins/qmlprojectmanager/qmlprojectplugin.cpp b/src/plugins/qmlprojectmanager/qmlprojectplugin.cpp index 2c1a294e7a..2ead9de6da 100644 --- a/src/plugins/qmlprojectmanager/qmlprojectplugin.cpp +++ b/src/plugins/qmlprojectmanager/qmlprojectplugin.cpp @@ -41,7 +41,7 @@ #include #include -#include +#include #include #include diff --git a/src/plugins/qmlprojectmanager/qmlprojectrunconfiguration.cpp b/src/plugins/qmlprojectmanager/qmlprojectrunconfiguration.cpp index 584bf8773b..1cce1650ce 100644 --- a/src/plugins/qmlprojectmanager/qmlprojectrunconfiguration.cpp +++ b/src/plugins/qmlprojectmanager/qmlprojectrunconfiguration.cpp @@ -34,7 +34,7 @@ #include #include #include -#include +#include #include #include diff --git a/src/plugins/qnx/qnxanalyzesupport.cpp b/src/plugins/qnx/qnxanalyzesupport.cpp index 29ea42b7cd..4d5a73b2ab 100644 --- a/src/plugins/qnx/qnxanalyzesupport.cpp +++ b/src/plugins/qnx/qnxanalyzesupport.cpp @@ -9,8 +9,7 @@ #include -#include -#include +#include #include diff --git a/src/plugins/qnx/qnxdebugsupport.cpp b/src/plugins/qnx/qnxdebugsupport.cpp index d6ee861898..919e9ef1fc 100644 --- a/src/plugins/qnx/qnxdebugsupport.cpp +++ b/src/plugins/qnx/qnxdebugsupport.cpp @@ -33,9 +33,9 @@ #include #include #include +#include #include #include -#include #include #include diff --git a/src/plugins/qnx/qnxdeployqtlibrariesdialog.cpp b/src/plugins/qnx/qnxdeployqtlibrariesdialog.cpp index 6450223e43..aef2b0d0cd 100644 --- a/src/plugins/qnx/qnxdeployqtlibrariesdialog.cpp +++ b/src/plugins/qnx/qnxdeployqtlibrariesdialog.cpp @@ -16,9 +16,9 @@ #include #include #include +#include #include #include -#include #include #include diff --git a/src/plugins/qnx/qnxdevice.cpp b/src/plugins/qnx/qnxdevice.cpp index 49056d9ec4..306b87e861 100644 --- a/src/plugins/qnx/qnxdevice.cpp +++ b/src/plugins/qnx/qnxdevice.cpp @@ -18,8 +18,8 @@ #include #include +#include #include -#include #include using namespace ProjectExplorer; diff --git a/src/plugins/qnx/qnxdevicetester.cpp b/src/plugins/qnx/qnxdevicetester.cpp index a96f5b6d7e..cbead1aa3d 100644 --- a/src/plugins/qnx/qnxdevicetester.cpp +++ b/src/plugins/qnx/qnxdevicetester.cpp @@ -6,8 +6,7 @@ #include "qnxconstants.h" #include "qnxtr.h" -#include -#include +#include using namespace Utils; diff --git a/src/plugins/qnx/qnxutils.cpp b/src/plugins/qnx/qnxutils.cpp index 3cc73e6d54..ba2c41b345 100644 --- a/src/plugins/qnx/qnxutils.cpp +++ b/src/plugins/qnx/qnxutils.cpp @@ -5,7 +5,7 @@ #include #include -#include +#include #include #include diff --git a/src/plugins/qnx/slog2inforunner.cpp b/src/plugins/qnx/slog2inforunner.cpp index 21de26e5a2..a6ceaab4cc 100644 --- a/src/plugins/qnx/slog2inforunner.cpp +++ b/src/plugins/qnx/slog2inforunner.cpp @@ -8,8 +8,8 @@ #include #include +#include #include -#include #include diff --git a/src/plugins/qtsupport/baseqtversion.cpp b/src/plugins/qtsupport/baseqtversion.cpp index c08f296a8c..179649c53b 100644 --- a/src/plugins/qtsupport/baseqtversion.cpp +++ b/src/plugins/qtsupport/baseqtversion.cpp @@ -33,8 +33,8 @@ #include #include #include +#include #include -#include #include #include diff --git a/src/plugins/qtsupport/externaleditors.cpp b/src/plugins/qtsupport/externaleditors.cpp index 9732693e6e..dffd730d28 100644 --- a/src/plugins/qtsupport/externaleditors.cpp +++ b/src/plugins/qtsupport/externaleditors.cpp @@ -19,8 +19,8 @@ #include #include #include +#include #include -#include #include #include diff --git a/src/plugins/qtsupport/qtsupportplugin.cpp b/src/plugins/qtsupport/qtsupportplugin.cpp index 37d141e11c..3fc9fe8fed 100644 --- a/src/plugins/qtsupport/qtsupportplugin.cpp +++ b/src/plugins/qtsupport/qtsupportplugin.cpp @@ -33,7 +33,7 @@ #include #include #include -#include +#include using namespace Core; using namespace Utils; diff --git a/src/plugins/qtsupport/qtversionmanager.cpp b/src/plugins/qtsupport/qtversionmanager.cpp index bde9d2e337..eedc79e686 100644 --- a/src/plugins/qtsupport/qtversionmanager.cpp +++ b/src/plugins/qtsupport/qtversionmanager.cpp @@ -21,8 +21,8 @@ #include #include #include +#include #include -#include #include #include diff --git a/src/plugins/qtsupport/uicgenerator.cpp b/src/plugins/qtsupport/uicgenerator.cpp index f48a8d310e..f1ff905b83 100644 --- a/src/plugins/qtsupport/uicgenerator.cpp +++ b/src/plugins/qtsupport/uicgenerator.cpp @@ -2,20 +2,21 @@ // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 #include "uicgenerator.h" + #include "baseqtversion.h" #include "qtkitinformation.h" +#include #include #include -#include +#include #include -#include -#include +#include #include +#include #include -#include using namespace ProjectExplorer; diff --git a/src/plugins/remotelinux/customcommanddeploystep.cpp b/src/plugins/remotelinux/customcommanddeploystep.cpp index 7249d2c6b2..670390eeb1 100644 --- a/src/plugins/remotelinux/customcommanddeploystep.cpp +++ b/src/plugins/remotelinux/customcommanddeploystep.cpp @@ -11,7 +11,7 @@ #include #include -#include +#include using namespace ProjectExplorer; using namespace Utils; diff --git a/src/plugins/remotelinux/filesystemaccess_test.cpp b/src/plugins/remotelinux/filesystemaccess_test.cpp index 24267b16bd..00fdd82f36 100644 --- a/src/plugins/remotelinux/filesystemaccess_test.cpp +++ b/src/plugins/remotelinux/filesystemaccess_test.cpp @@ -11,8 +11,8 @@ #include #include #include +#include #include -#include #include #include diff --git a/src/plugins/remotelinux/genericdirectuploadstep.cpp b/src/plugins/remotelinux/genericdirectuploadstep.cpp index 4889dbb35d..e4e3ed3801 100644 --- a/src/plugins/remotelinux/genericdirectuploadstep.cpp +++ b/src/plugins/remotelinux/genericdirectuploadstep.cpp @@ -15,9 +15,9 @@ #include #include +#include #include #include -#include #include diff --git a/src/plugins/remotelinux/linuxdevice.cpp b/src/plugins/remotelinux/linuxdevice.cpp index 6aca035bb6..31980f6761 100644 --- a/src/plugins/remotelinux/linuxdevice.cpp +++ b/src/plugins/remotelinux/linuxdevice.cpp @@ -29,9 +29,9 @@ #include #include #include +#include #include #include -#include #include #include diff --git a/src/plugins/remotelinux/linuxdevicetester.cpp b/src/plugins/remotelinux/linuxdevicetester.cpp index c28b2ecfc5..39df7d9403 100644 --- a/src/plugins/remotelinux/linuxdevicetester.cpp +++ b/src/plugins/remotelinux/linuxdevicetester.cpp @@ -10,9 +10,9 @@ #include #include +#include #include #include -#include #include using namespace ProjectExplorer; diff --git a/src/plugins/remotelinux/makeinstallstep.cpp b/src/plugins/remotelinux/makeinstallstep.cpp index e5641abec0..d1be105145 100644 --- a/src/plugins/remotelinux/makeinstallstep.cpp +++ b/src/plugins/remotelinux/makeinstallstep.cpp @@ -20,8 +20,8 @@ #include #include +#include #include -#include #include #include diff --git a/src/plugins/remotelinux/publickeydeploymentdialog.cpp b/src/plugins/remotelinux/publickeydeploymentdialog.cpp index c5564d3c74..c7b4a54810 100644 --- a/src/plugins/remotelinux/publickeydeploymentdialog.cpp +++ b/src/plugins/remotelinux/publickeydeploymentdialog.cpp @@ -10,7 +10,7 @@ #include #include -#include +#include #include #include diff --git a/src/plugins/remotelinux/remotelinuxsignaloperation.cpp b/src/plugins/remotelinux/remotelinuxsignaloperation.cpp index 4ee28e7701..816e0e3869 100644 --- a/src/plugins/remotelinux/remotelinuxsignaloperation.cpp +++ b/src/plugins/remotelinux/remotelinuxsignaloperation.cpp @@ -7,8 +7,8 @@ #include #include +#include #include -#include using namespace ProjectExplorer; using namespace Utils; diff --git a/src/plugins/remotelinux/rsyncdeploystep.cpp b/src/plugins/remotelinux/rsyncdeploystep.cpp index 7a161601b7..b0779c01e2 100644 --- a/src/plugins/remotelinux/rsyncdeploystep.cpp +++ b/src/plugins/remotelinux/rsyncdeploystep.cpp @@ -16,8 +16,8 @@ #include #include +#include #include -#include #include using namespace ProjectExplorer; diff --git a/src/plugins/remotelinux/sshkeycreationdialog.cpp b/src/plugins/remotelinux/sshkeycreationdialog.cpp index 16dcf9220d..441edab889 100644 --- a/src/plugins/remotelinux/sshkeycreationdialog.cpp +++ b/src/plugins/remotelinux/sshkeycreationdialog.cpp @@ -10,7 +10,7 @@ #include #include #include -#include +#include #include #include diff --git a/src/plugins/remotelinux/tarpackagedeploystep.cpp b/src/plugins/remotelinux/tarpackagedeploystep.cpp index 4f517ea91d..a79209354a 100644 --- a/src/plugins/remotelinux/tarpackagedeploystep.cpp +++ b/src/plugins/remotelinux/tarpackagedeploystep.cpp @@ -12,8 +12,8 @@ #include #include +#include #include -#include using namespace ProjectExplorer; using namespace Utils; diff --git a/src/plugins/silversearcher/findinfilessilversearcher.cpp b/src/plugins/silversearcher/findinfilessilversearcher.cpp index e2a85ab53c..9ac9702a6e 100644 --- a/src/plugins/silversearcher/findinfilessilversearcher.cpp +++ b/src/plugins/silversearcher/findinfilessilversearcher.cpp @@ -9,8 +9,8 @@ #include #include #include +#include #include -#include #include "silversearcheroutputparser.h" #include "silversearchertr.h" diff --git a/src/plugins/squish/objectsmapdocument.cpp b/src/plugins/squish/objectsmapdocument.cpp index 0555bb3512..3742ee3466 100644 --- a/src/plugins/squish/objectsmapdocument.cpp +++ b/src/plugins/squish/objectsmapdocument.cpp @@ -10,7 +10,7 @@ #include "squishtr.h" #include -#include +#include #include diff --git a/src/plugins/squish/squishprocessbase.h b/src/plugins/squish/squishprocessbase.h index d8af2e9d4f..6582c95062 100644 --- a/src/plugins/squish/squishprocessbase.h +++ b/src/plugins/squish/squishprocessbase.h @@ -5,7 +5,7 @@ #include "squishconstants.h" -#include +#include #include diff --git a/src/plugins/squish/squishtools.h b/src/plugins/squish/squishtools.h index 19b57a7cb4..8d3cf61cfc 100644 --- a/src/plugins/squish/squishtools.h +++ b/src/plugins/squish/squishtools.h @@ -9,7 +9,7 @@ #include "suiteconf.h" #include -#include +#include #include #include diff --git a/src/plugins/subversion/subversionclient.cpp b/src/plugins/subversion/subversionclient.cpp index c9b28724ea..45cd652381 100644 --- a/src/plugins/subversion/subversionclient.cpp +++ b/src/plugins/subversion/subversionclient.cpp @@ -12,8 +12,7 @@ #include #include #include -#include -#include +#include #include #include diff --git a/src/plugins/terminal/shellintegration.h b/src/plugins/terminal/shellintegration.h index 8fce983b01..a4a813c8a6 100644 --- a/src/plugins/terminal/shellintegration.h +++ b/src/plugins/terminal/shellintegration.h @@ -5,7 +5,7 @@ #pragma once #include -#include +#include #include diff --git a/src/plugins/terminal/terminalwidget.h b/src/plugins/terminal/terminalwidget.h index f6ea7d763b..4f56f39efe 100644 --- a/src/plugins/terminal/terminalwidget.h +++ b/src/plugins/terminal/terminalwidget.h @@ -9,7 +9,7 @@ #include #include -#include +#include #include #include diff --git a/src/plugins/texteditor/formattexteditor.cpp b/src/plugins/texteditor/formattexteditor.cpp index 5f02b7e9d0..3e31006d61 100644 --- a/src/plugins/texteditor/formattexteditor.cpp +++ b/src/plugins/texteditor/formattexteditor.cpp @@ -12,8 +12,8 @@ #include #include +#include #include -#include #include #include diff --git a/src/plugins/updateinfo/updateinfoplugin.cpp b/src/plugins/updateinfo/updateinfoplugin.cpp index 8ee3247010..d6ec407f63 100644 --- a/src/plugins/updateinfo/updateinfoplugin.cpp +++ b/src/plugins/updateinfo/updateinfoplugin.cpp @@ -13,8 +13,8 @@ #include #include #include +#include #include -#include #include #include diff --git a/src/plugins/valgrind/callgrindengine.cpp b/src/plugins/valgrind/callgrindengine.cpp index 2c2f73b10e..99d948c248 100644 --- a/src/plugins/valgrind/callgrindengine.cpp +++ b/src/plugins/valgrind/callgrindengine.cpp @@ -13,8 +13,8 @@ #include #include +#include #include -#include #include #include diff --git a/src/plugins/valgrind/callgrindengine.h b/src/plugins/valgrind/callgrindengine.h index 13d04b6335..4ec6a16d7f 100644 --- a/src/plugins/valgrind/callgrindengine.h +++ b/src/plugins/valgrind/callgrindengine.h @@ -8,7 +8,7 @@ #include "callgrind/callgrindparsedata.h" #include "callgrind/callgrindparser.h" -#include +#include namespace Valgrind { namespace Internal { diff --git a/src/plugins/valgrind/callgrindtool.cpp b/src/plugins/valgrind/callgrindtool.cpp index 9b35de452d..ab5b0e5560 100644 --- a/src/plugins/valgrind/callgrindtool.cpp +++ b/src/plugins/valgrind/callgrindtool.cpp @@ -52,8 +52,8 @@ #include #include +#include #include -#include #include #include diff --git a/src/plugins/valgrind/memchecktool.cpp b/src/plugins/valgrind/memchecktool.cpp index b07288b175..e0702ef972 100644 --- a/src/plugins/valgrind/memchecktool.cpp +++ b/src/plugins/valgrind/memchecktool.cpp @@ -50,8 +50,8 @@ #include #include #include +#include #include -#include #include #include diff --git a/src/plugins/valgrind/valgrindrunner.cpp b/src/plugins/valgrind/valgrindrunner.cpp index 3750217ad7..ef78c7f9ff 100644 --- a/src/plugins/valgrind/valgrindrunner.cpp +++ b/src/plugins/valgrind/valgrindrunner.cpp @@ -9,8 +9,8 @@ #include #include +#include #include -#include #include #include diff --git a/src/plugins/vcsbase/vcsbaseclient.cpp b/src/plugins/vcsbase/vcsbaseclient.cpp index b781b1772a..d5ec691ec0 100644 --- a/src/plugins/vcsbase/vcsbaseclient.cpp +++ b/src/plugins/vcsbase/vcsbaseclient.cpp @@ -21,8 +21,8 @@ #include #include +#include #include -#include #include #include diff --git a/src/plugins/vcsbase/vcsbasediffeditorcontroller.cpp b/src/plugins/vcsbase/vcsbasediffeditorcontroller.cpp index aaea619a2b..715b085559 100644 --- a/src/plugins/vcsbase/vcsbasediffeditorcontroller.cpp +++ b/src/plugins/vcsbase/vcsbasediffeditorcontroller.cpp @@ -8,8 +8,8 @@ #include #include #include +#include #include -#include using namespace DiffEditor; using namespace Utils; diff --git a/src/plugins/vcsbase/vcsbaseplugin.cpp b/src/plugins/vcsbase/vcsbaseplugin.cpp index dfd89842c5..517ffbdf48 100644 --- a/src/plugins/vcsbase/vcsbaseplugin.cpp +++ b/src/plugins/vcsbase/vcsbaseplugin.cpp @@ -17,8 +17,8 @@ #include #include +#include #include -#include #include #include diff --git a/src/plugins/vcsbase/vcsbasesubmiteditor.cpp b/src/plugins/vcsbase/vcsbasesubmiteditor.cpp index 0d9f92a702..d9717ece09 100644 --- a/src/plugins/vcsbase/vcsbasesubmiteditor.cpp +++ b/src/plugins/vcsbase/vcsbasesubmiteditor.cpp @@ -28,8 +28,8 @@ #include #include #include +#include #include -#include #include #include diff --git a/src/plugins/vcsbase/vcscommand.cpp b/src/plugins/vcsbase/vcscommand.cpp index a16545b70b..885ff004da 100644 --- a/src/plugins/vcsbase/vcscommand.cpp +++ b/src/plugins/vcsbase/vcscommand.cpp @@ -10,8 +10,8 @@ #include #include +#include #include -#include #include #include diff --git a/src/plugins/vcsbase/vcsoutputwindow.cpp b/src/plugins/vcsbase/vcsoutputwindow.cpp index 245de85134..2b5536809f 100644 --- a/src/plugins/vcsbase/vcsoutputwindow.cpp +++ b/src/plugins/vcsbase/vcsoutputwindow.cpp @@ -14,7 +14,7 @@ #include #include -#include +#include #include #include diff --git a/src/plugins/webassembly/webassemblyemsdk.cpp b/src/plugins/webassembly/webassemblyemsdk.cpp index e66df1272d..42f8738a8e 100644 --- a/src/plugins/webassembly/webassemblyemsdk.cpp +++ b/src/plugins/webassembly/webassemblyemsdk.cpp @@ -7,7 +7,7 @@ #include #include -#include +#include #include #include diff --git a/src/plugins/webassembly/webassemblyrunconfigurationaspects.cpp b/src/plugins/webassembly/webassemblyrunconfigurationaspects.cpp index 70484168eb..05b7e89e82 100644 --- a/src/plugins/webassembly/webassemblyrunconfigurationaspects.cpp +++ b/src/plugins/webassembly/webassemblyrunconfigurationaspects.cpp @@ -8,8 +8,8 @@ #include #include +#include #include -#include #include #include diff --git a/tests/auto/utils/commandline/tst_commandline.cpp b/tests/auto/utils/commandline/tst_commandline.cpp index c20eb48db9..2691b1e84a 100644 --- a/tests/auto/utils/commandline/tst_commandline.cpp +++ b/tests/auto/utils/commandline/tst_commandline.cpp @@ -8,8 +8,8 @@ #include #include #include +#include #include -#include #include #include diff --git a/tests/auto/utils/deviceshell/tst_deviceshell.cpp b/tests/auto/utils/deviceshell/tst_deviceshell.cpp index f94d0dc5b4..6e081495c3 100644 --- a/tests/auto/utils/deviceshell/tst_deviceshell.cpp +++ b/tests/auto/utils/deviceshell/tst_deviceshell.cpp @@ -8,7 +8,7 @@ #include #include #include -#include +#include #include #include diff --git a/tests/auto/utils/qtcprocess/processtestapp/main.cpp b/tests/auto/utils/qtcprocess/processtestapp/main.cpp index 6851a3597c..91952c2528 100644 --- a/tests/auto/utils/qtcprocess/processtestapp/main.cpp +++ b/tests/auto/utils/qtcprocess/processtestapp/main.cpp @@ -6,7 +6,7 @@ #include #include -#include +#include #include #include diff --git a/tests/auto/utils/qtcprocess/processtestapp/processtestapp.cpp b/tests/auto/utils/qtcprocess/processtestapp/processtestapp.cpp index 1fa73a9475..3905d0a22b 100644 --- a/tests/auto/utils/qtcprocess/processtestapp/processtestapp.cpp +++ b/tests/auto/utils/qtcprocess/processtestapp/processtestapp.cpp @@ -3,7 +3,7 @@ #include "processtestapp.h" -#include +#include #include #include diff --git a/tests/auto/utils/qtcprocess/tst_qtcprocess.cpp b/tests/auto/utils/qtcprocess/tst_qtcprocess.cpp index 1bc1778237..657b335606 100644 --- a/tests/auto/utils/qtcprocess/tst_qtcprocess.cpp +++ b/tests/auto/utils/qtcprocess/tst_qtcprocess.cpp @@ -8,10 +8,10 @@ #include #include #include +#include #include #include #include -#include #include #include #include diff --git a/tests/manual/deviceshell/tst_deviceshell.cpp b/tests/manual/deviceshell/tst_deviceshell.cpp index 96638763f8..99c506d1bd 100644 --- a/tests/manual/deviceshell/tst_deviceshell.cpp +++ b/tests/manual/deviceshell/tst_deviceshell.cpp @@ -6,7 +6,7 @@ #include #include #include -#include +#include #include #include -- cgit v1.2.3