Commit Graph

63 Commits

Author SHA1 Message Date
Aaron Barany
df0593b5e1 Utils: Preserve output order with merged channels
Restored the process channel mode members to ProcessSetupData and
StartProcessPacket and forward to the QProcess created in
LaunchSocketHandler. LaunchSocketHandler now avoids reading from stderr
for merged channels since it's guaranteed to not be available.

This avoids asserts in Qt 6.3.0 and warnings in Qt 6.3.1 while
preserving the original output order when an application has a mix of
stdout and stderr output.

Change-Id: I9f4541932cf9d8638b38658a5efea9cb5f1798f3
Reviewed-by: Jarek Kobus <jaroslaw.kobus@qt.io>
2022-04-19 19:39:24 +00:00
Jarek Kobus
bc30523293 ProcessInterface: Get rid of ProcessInterface::Ptr
Keep the setup data on stack instead on heap.

Task-number: QTCREATORBUG-27358
Change-Id: I0fffd525e2bd4f46533804e3b88fe5b330d02a91
Reviewed-by: hjk <hjk@qt.io>
Reviewed-by: <github-actions-qt-creator@cristianadam.eu>
2022-04-14 12:41:01 +00:00
Jarek Kobus
267aa92a8a ProcessInterface: Pass processId with started() signal
Pass also applicationMainThreadId optionally (Windows only).
Remove two virtual accessors.

Task-number: QTCREATORBUG-27358
Change-Id: I3b12b642cc3c109653276c0fbf65e7f614ce6b56
Reviewed-by: David Schulz <david.schulz@qt.io>
Reviewed-by: hjk <hjk@qt.io>
Reviewed-by: <github-actions-qt-creator@cristianadam.eu>
2022-04-13 14:39:18 +00:00
Jarek Kobus
aa3f467ee2 ProcessInterface: Add readyRead() signal
And get rid of readyReadStandard[Output/Error]() signals.
Get rid of readAllStandard[Output/Error]() accessors, as
this data is passed with readyRead() signal.

Task-number: QTCREATORBUG-27358
Change-Id: I01341feba650e650761f97e90f83b6042c899251
Reviewed-by: hjk <hjk@qt.io>
Reviewed-by: <github-actions-qt-creator@cristianadam.eu>
2022-04-12 14:00:14 +00:00
Jarek Kobus
4ca336762e ProcessInterface: Add done() signal
And get rid of errorOccurred() and finished() signals.
Get rid of resultData() accessor, as this data is passed
with done() signal.

Task-number: QTCREATORBUG-27358
Change-Id: I677bbd174cceea6d8f5a989f961222c417992b60
Reviewed-by: hjk <hjk@qt.io>
Reviewed-by: <github-actions-qt-creator@cristianadam.eu>
2022-04-12 14:00:03 +00:00
Jarek Kobus
00acccfd3d QtcProcess: Fix terminate() for process launcher
ProcessLauncherImpl::terminate() was behaving the same as
ProcessLauncherImpl::kill() in case of process launcher
implementation - in both cases the launcher
immediately returned confirmation about receiving the
close request and was putting the corresponding
process into its reaper. However, the issue with this approach
is that we can't receive anymore any potential ready
read signal from the process being terminated after
a call to terminate().

The fix is to diverge the behavior of terminate()
and kill() of ProcessLauncherImpl. The behavior of kill()
remains the same, while terminate() just instructs the
process launcher to start termination without putting
the process into the reaper, yet.

Add a test that checks for any possible zombies.

We run the RecursiveBlockingProcess recursively. The most
nested process blocks. After a short wait we terminate
the outermost process. With this test we are trying to see
if terminating the middle process terminates also its
children and doesn't leave zombies.

Before we execute the test (and also by the end of this test)
we call Singleton::deleteAll() in order to ensure that reaping
of previously running processes has finished. We ensure the
number of running processtestapps is zero. Later, we ensure that
the leaf process was already started and the number of running
processtestapps equals the depth of recursion.

Fix apparent bug in getLocalProcessesUsingProc().

Change-Id: I7e2bc46ad5ca22f26620da86fbaf0fa00a7db3c3
Reviewed-by: hjk <hjk@qt.io>
Reviewed-by: <github-actions-qt-creator@cristianadam.eu>
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
2022-04-12 13:59:41 +00:00
Jarek Kobus
936c44f367 Introduce ProcessResultData
It should be useful when reimplementing ProcessInterface.
It replaces 4 virtual methods with just 1.

Task-number: QTCREATORBUG-27358
Change-Id: I2dafbfbc25f8f016ff2aa19c1a176335a4a7498c
Reviewed-by: hjk <hjk@qt.io>
2022-04-11 06:51:51 +00:00
Jarek Kobus
365a05640b QtcProcess: Get rid of setErrorString() method
It's internal method, not meant to be used outside.
It's only used in case of FailedToStart error.
Remove it also from ProcessInterface.
Leave it inside DefaultImpl and its subclasses only.

Remove m_errorString field from ProcessSetupData.

Change-Id: Ie605b95c2ff605ab1259045f1a5b16049207c1d3
Reviewed-by: hjk <hjk@qt.io>
2022-04-04 10:20:34 +00:00
Jarek Kobus
afd70a2c67 StartProcessPacket: Get rid of m_processChannelMode
We handle process merging in CallerHandle.

Amends de1bef18e2

Change-Id: I682d600c3ddb0306167389b77cfae8181c1dc9d1
Reviewed-by: hjk <hjk@qt.io>
2022-03-31 13:22:51 +00:00
Jarek Kobus
b76b8b1542 ProcessReaper: Implement custom terminate for CtrlCStub case
Move CtrlCStub-specific interrupt into ProcessHelper.

Amends 7d7e4af3afb5ba9d0ed5210018dd6be67abda469

Change-Id: I5cd9a750c4a89587a874515f752b0144df4b8309
Reviewed-by: hjk <hjk@qt.io>
2022-03-31 12:48:42 +00:00
hjk
de1bef18e2 Utils: Work around readAllStandardError() with QProcess::MergedChannels
Instead of relying QProcess to operate with MergedChannels, keep
the separate channels and merge inside QtcProcess.

Fixes: QTCREATORBUG-27196
Change-Id: I3039267fcd6d90f95f8212642e17049b87af1156
Reviewed-by: Jarek Kobus <jaroslaw.kobus@qt.io>
2022-03-31 11:13:16 +00:00
Jarek Kobus
8da44324e7 QtcProcess: Resolve old TODO, add new asserts
Add new TODO, too.

Change-Id: Ia1844638054099fdc2aae1878fa21c133f6023ef
Reviewed-by: hjk <hjk@qt.io>
Reviewed-by: <github-actions-qt-creator@cristianadam.eu>
2022-03-31 10:28:44 +00:00
Jarek Kobus
cfe8b7ad88 Fix handling of unfinished lines by QtcProcess callbacks
Don't detect a call to QtcProcess::kill() from inside the
QtcProcess callback while awaiting inside QtcProcess::waitFor...().
That's not needed, since a call to kill() sends a stop message
to the process launcher, so we wait for confirmation
from process launcher instead. This may bring e.g. new
read data from the running process.

Fix a runBlockingStdOut() test so that when we write to the stdOut
from the running process we flush the unfinished line so that
it's not buffered inside the process.

Change-Id: I7944ac214d8cb9e10a71715a7ef8bfacab6df7c9
Reviewed-by: Alessandro Portale <alessandro.portale@qt.io>
Reviewed-by: <github-actions-qt-creator@cristianadam.eu>
2022-03-14 07:38:08 +00:00
Robert Löhning
7c942cfd18 Remove outdated code
Change-Id: I65e0ed79dabd987bc67d4082969835d52dd7cb8b
Reviewed-by: Eike Ziller <eike.ziller@qt.io>
Reviewed-by: <github-actions-qt-creator@cristianadam.eu>
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
2022-03-09 18:53:36 +00:00
Jarek Kobus
ac3aa805b9 QtcProcess: Ensure we set the data just after creating handle
...instead of ensuring in many functions that m_setup isn't null.
This amends 36c49cd2ea and
solves the issue for other functions like processId(),
exitCode(), etc...

Amends 36c49cd2ea

Change-Id: I986f7b30e90e5825ae2bb57b4bc2aa14f56e401f
Reviewed-by: <github-actions-qt-creator@cristianadam.eu>
Reviewed-by: hjk <hjk@qt.io>
2022-03-03 10:02:36 +00:00
hjk
36c49cd2ea Utils: Prevent early crash on non-existent commands
Change-Id: Ib94920835396e34827e7b40c30f48d28660e5fcf
Reviewed-by: hjk <hjk@qt.io>
2022-03-02 16:35:28 +00:00
Jarek Kobus
a17374778a Introduce ProcessProxyInterface, enable data sharing
ProcessProxyInterface will be helpful when implementing
public subclasses of ProcessInterface, like
general ssh impl, linux specific impl, qnx specific, etc.

ProcessProxyInterface is sharing private data
between proxy and target.

Change-Id: I8350837bb5f770d6605b860b146604cba5e6b592
Reviewed-by: hjk <hjk@qt.io>
2022-03-02 15:31:13 +00:00
Eike Ziller
8259df00d0 Merge remote-tracking branch 'origin/7.0'
Conflicts:
	src/plugins/mcusupport/mcupackage.cpp
	src/plugins/mcusupport/mcusupportoptions.cpp
	src/plugins/mcusupport/mcusupportoptions.h
	src/plugins/mcusupport/mcusupportoptionspage.cpp
	src/plugins/mcusupport/mcusupportplugin.cpp
	src/plugins/mcusupport/mcusupportsdk.cpp

Change-Id: Ib423e9f23877176f01b188104b0a179ed32c4770
2022-02-22 14:06:41 +01:00
Jarek Kobus
fdc8193f13 ProcessInterface: Drop ProcessMode from c'tor
Drop it also from registerHandle() methods, as it wasn't
used there.

Change-Id: I34b72c38368b82f22d73314fe3cd429ed43cadbc
Reviewed-by: hjk <hjk@qt.io>
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
2022-02-18 08:29:24 +00:00
Jarek Kobus
ae36fd943a ProcessInterface: Drop arguments from finished() signal
Make the API more similar to QtcProcess API.

Change-Id: If62051908b7974008bebda21dd288b02e7a772f3
Reviewed-by: hjk <hjk@qt.io>
2022-02-17 16:58:19 +00:00
Leena Miettinen
2a1ce51ce3 Utils: Fix UI text punctuation and capitalization
Also simplify the wording of a message.

Task-number: QTCREATORBUG-27055
Change-Id: I29df31f8484d451d8d8d1869ca3a1b182072d2c1
Reviewed-by: Jarek Kobus <jaroslaw.kobus@qt.io>
2022-02-16 16:57:17 +00:00
Jarek Kobus
82c2450fbe Reuse ProcessSetupData in CallerHandle
Change-Id: I4a2d3fef15331343e7763149550280b722fc3781
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: <github-actions-qt-creator@cristianadam.eu>
Reviewed-by: hjk <hjk@qt.io>
2022-02-16 09:30:01 +00:00
Jarek Kobus
5c3a08bc4b ProcessInterface: Simplify start() method
Don't pass writeData, as that's available through
ProcessSetupData.

Change-Id: Ic55b21c6a3338168ee251bcc1c57594f50c52d2f
Reviewed-by: <github-actions-qt-creator@cristianadam.eu>
Reviewed-by: hjk <hjk@qt.io>
2022-02-16 09:09:24 +00:00
Jarek Kobus
6f1285f508 ProcessInterface: Use Environment and FilePath
Use Utils::Environment for of environment.
Use Utils::FilePath for workingDirectory.

Change-Id: I6b717139f8ff7ddbd629fb22cf816b2303fb5e6a
Reviewed-by: hjk <hjk@qt.io>
2022-02-14 15:16:30 +00:00
Jarek Kobus
e7d125ffec ProcessLauncher: stop awaiting for ready read when finished
In case the user called waitForReadyRead() and we have
received the finished signal instead (without receiving
readyRead signals in meantime), we should interrupt
the wait and return false, since there is no point to
wait for future readyRead signals from not running process.

Change-Id: Ib4a770aea6ed562a5bef197eaa51b20c146842f0
Reviewed-by: hjk <hjk@qt.io>
Reviewed-by: <github-actions-qt-creator@cristianadam.eu>
2022-01-13 14:08:55 +00:00
Jarek Kobus
0830e50185 Fix "forever" timeout in QtcProcess::waitFor... methods
Change-Id: I57aac503599fa94f530e073164b86b5247702ce5
Reviewed-by: Alessandro Portale <alessandro.portale@qt.io>
2021-11-05 17:46:56 +00:00
Jarek Kobus
acfe224281 Flush finished() signal when waitForReadyRead() was called
Apparently the QProcess behaves like that.

Change-Id: Idb1993b8abccbd7943582d41bd456eacc9a1c185
Reviewed-by: hjk <hjk@qt.io>
Reviewed-by: Alessandro Portale <alessandro.portale@qt.io>
2021-11-04 12:30:03 +00:00
Leena Miettinen
dcd4d1c92e Launcher: Fix UI text
Task-number: QTCREATORBUG-26458
Change-Id: I99ffa236a58dd9bdad9716edfdd7a576293144d8
Reviewed-by: Jarek Kobus <jaroslaw.kobus@qt.io>
2021-10-25 15:14:33 +00:00
Jarek Kobus
f7aa963a07 Make all objects created by QtcProcess children of it
Sometimes after creating QtcProcess we move it into a different
thread. In this case we should move all the children, too.
Without parent-child relation all the children will stay in the
old thread.

Change-Id: Ibde44d6153092a155dd2d200a7116a046910dddc
Reviewed-by: Christian Kandeler <christian.kandeler@qt.io>
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
2021-09-03 10:56:26 +00:00
Jarek Kobus
a454b3dc23 Use QProcess' / process lanuncher's exit code
Change-Id: I802116c45847daf9a647771ee293aef8463fc3c7
Reviewed-by: Christian Kandeler <christian.kandeler@qt.io>
2021-09-03 10:56:19 +00:00
Jarek Kobus
597750507e Implement process channel forwarding in process launcher
Change-Id: I9e526eb40ebc46284f773d10ec0e285a009c524d
Reviewed-by: Christian Kandeler <christian.kandeler@qt.io>
2021-09-03 10:56:12 +00:00
Christian Kandeler
3be9f52980 Fix some warnings
Unused functions & variables, initialization order, signedness, non-
virtual destructor.

Change-Id: I405d768fe0e02a36a16c2cead9e1bc2f6a23fb75
Reviewed-by: Christian Stenger <christian.stenger@qt.io>
2021-09-02 13:47:07 +00:00
Jarek Kobus
15c183fce6 Set process state to NotRunning after FailedToStart error
Remove the process in process launcher after error has appeared.
Remove unneeded stopStopProcedure as we are disconnecting from
process' signals inside removeProcess().
In order to behave as much similar to what QProcess does,
provide a test that:
- ensures the FailedToStart error is synchronously emitted
  when waitForStarted is being executed
- ensures that process state is reset to NotRunning after
  FailedToStart error
- 2nd call to start/waitForStarted doesn't block on
  waitForStarted

Change-Id: I139354421d037739f1cc1a2685b66f1e5b6170c8
Reviewed-by: Christian Stenger <christian.stenger@qt.io>
2021-08-31 12:09:36 +00:00
Jarek Kobus
99cf99579e Make access to LauncherSocket thread safe
Instead of returning a pointer to LauncherSocket instance,
which might get deleted in meantime of just after,
route all calls to the LauncherSocket through the LauncherInterface.
Make all calls to LauncherInterface secured by the
instance mutex.

Change-Id: I751228de5f4263112471098ee08cc73a5245147e
Reviewed-by: hjk <hjk@qt.io>
Reviewed-by: Eike Ziller <eike.ziller@qt.io>
2021-08-31 08:45:59 +00:00
Jarek Kobus
98d7261c67 Assert that when stopping the launcher no QtcProcess exists
Otherwise such a QtcProcess won't work properly anymore.

Change-Id: I9eb7c8beb864a895a60c0e60ff394e74c35a0ebb
Reviewed-by: hjk <hjk@qt.io>
2021-08-31 06:31:24 +00:00
Jarek Kobus
98de1c5544 Pass lowPriority and unixTerminalDisabled into process launcher
Amends b80624611b

Change-Id: I8a050d8e9f8b73a0e93c06fe017f16403884574b
Reviewed-by: hjk <hjk@qt.io>
2021-08-31 06:13:51 +00:00
Jarek Kobus
c145f95952 Add a virtual destructor for the LauncherSignal base class
Move qDeleteAll into cpp file, as LauncherSignal is defined there.

Change-Id: I59ed1de2025c3f62196e1c676accf26b3fb813ac
Reviewed-by: Eike Ziller <eike.ziller@qt.io>
2021-08-30 08:29:50 +00:00
Jarek Kobus
7814605215 Don't start the process when being in running state
Assert that we are in NotRunning state when starting a process.
Otherwise we issue a warning and ignore the new call.

Change-Id: Ie8c007851aabb4b814c1fd49bc8d01f22eb1a563
Reviewed-by: hjk <hjk@qt.io>
2021-08-25 08:36:31 +00:00
Jarek Kobus
5fe210c7db Merge multiple ready read signals into one
This minimizes the amount of readyRead() signals emitted.

Change-Id: Ibd2409d6f273a2781839a73220cf41e57a941e54
Reviewed-by: hjk <hjk@qt.io>
2021-08-25 07:04:28 +00:00
Jarek Kobus
1a5db9ca4e Refactor CallerHandle / LauncherHandle
Fix a race condition in the following scenario:

  QtcProcess proc(...)
  ...
  proc.start();
  proc.waitForStarted();
  if (!proc.waitForFinished()) {
      // handle failure here
      return;
  }
  // handle success

Move all the data into the caller's handle
and manage the QtcProcess state only from
inside caller's thread. This eliminates race
conditions when state changed from inside launcher's
thread while the caller's thread isn't notified
immediately.

For example: currently, when the launcher's thread receives
finished signal it doesn't change the process state
immediately, but posts a finished signal to be
dispatched in the caller's thread. When the caller's
thread dispatches the posted signal (inside flush() method)
it changes its state and posts the finished signal to the
outside world.

Don't flush all signals from waitForStarted(). Flush
only started signal in this case.

Change-Id: Ia39c4021bf43b8d0e8fcda789c367c096bfd032c
Reviewed-by: hjk <hjk@qt.io>
2021-08-24 18:24:18 +00:00
Jarek Kobus
7bc8672968 Assert that startLauncher() was called before starting any QtcProcess
Change-Id: Ieab97f7428c04ba90fc9a637ed8c29c8e97dec69
Reviewed-by: Christian Stenger <christian.stenger@qt.io>
2021-08-20 10:31:27 +00:00
Jarek Kobus
a09bedf1cb Conform to Creator's include style
Get rid of <QtModule/qclass.h> style and use <QClass> directly,
like in all other places in Creator. Remove some unneeded
declarations.

Change-Id: I1b5630850c570e5d86df01a341f7352bc1971e48
Reviewed-by: hjk <hjk@qt.io>
2021-08-19 15:59:03 +00:00
Jarek Kobus
bd5b6b60c9 Add asserts ensuring that methods are called from right threads
Change-Id: I4f6d8dc706f89c3fb043655d775d02f878c546d6
Reviewed-by: hjk <hjk@qt.io>
2021-08-18 14:14:47 +00:00
Jarek Kobus
a7e8ddd725 Add some more comments
Add some developer comments explaining which method
is designed to be called from a certain thread.
Add also some comments about in which thread
certain QObjects live in.

Change-Id: I38b10216cc29f8a86fd784e588e913407f0fb776
Reviewed-by: hjk <hjk@qt.io>
2021-08-18 10:24:18 +00:00
Jarek Kobus
43de2deebc Wake up QtcProcess when error occurred
Pipe the error packet through the caller's handle and flush
it immediately if the caller was awaiting for any signal.
Stop awaiting for any signal when we have flushed error signal.
In this case return false from waitForSignal() method
in order to mimic the QProcess behavior.

Fixes: QTCREATORBUG-26136
Change-Id: Ie80b4a63bd19a6309d4791ad39a698bd91bb8967
Reviewed-by: hjk <hjk@qt.io>
Reviewed-by: Christian Kandeler <christian.kandeler@qt.io>
2021-08-18 10:19:28 +00:00
Jarek Kobus
7726267d07 Fix a deadlock when doStart() is called from launcher's thread
In case when QtcProcess::start() is being called very early,
just after the launcher socket was started but not ready yet,
a start is being delayed. In this case doStart() isn't
called directly from the caller's thread, but it will be
invoked later from the launcher's thread, when the socket is ready.
In this case we may have a deadlock, since calling
doStart(), sendPacket(), sendData() and finally handleRequests()
results in a synchonous chain of calls in launcher's thread,
so the mutex locked in sendData() will block synchronous call to
handleRequests(). In order to fix it we unlock the mutex
in sendData() before calling handleRequests().

Change-Id: I6c13994d0b05b624567c75ffbd2ac7cc0d77df61
Reviewed-by: hjk <hjk@qt.io>
2021-08-17 12:23:39 +00:00
Jarek Kobus
9a73d394c3 Compile fix
Amends 837a707ec7

Change-Id: Icf1fa0a2536a57c8182bf7a3e651f9f2ab420516
Reviewed-by: Christian Stenger <christian.stenger@qt.io>
2021-08-17 08:56:29 +00:00
Jarek Kobus
837a707ec7 Fix a crazy case when waitingForFinished should process ReadyRead
Fix "runBlockingStdOut" autotest for tst_qtcprocess.
This crazy case relies on the fact that a blocking
call to waitForFinished() lets ReadyRead signals to
be processed in meantime and the handler for ReadyRead
may terminate the process. However, when no handler
for ReadyRead canceled the process, the blocking call to
waitForFinished() should return to the awaiting state
for the remaining time. From the caller's side everything
happens during a blocking invocation of waitForFinished().

So, in order to behave like this we implement waitForSignal()
in a loop. After we have flushed all the pending signals
we check if we have flushed the signal we were awaiting for.
If so, we break the loop, otherwise we continue. In order
to detect the case when the cancel was called during flushing
we set the m_awaitingShouldContinue flag before flushing.
The cancel() method clears this flag. Then after flushing
we check if the flag was cleared - in this case we don't
continue awaiting.

We reset the m_waitingFor state always after wait condition
finishes awaiting. Before, we didn't reset it when the
wait condition timed out.

Change-Id: I210f446659cabfd89bdfdd1fc8e8396d9470effc
Reviewed-by: hjk <hjk@qt.io>
2021-08-17 08:15:06 +00:00
Jarek Kobus
be6299a50a Fix compiler warning about suggested parentheses
Change-Id: Ibe7e32676bcae43ee270273c7a79ab959172d5b0
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: hjk <hjk@qt.io>
2021-08-12 04:22:29 +00:00
Jarek Kobus
4e06d3ac74 Handle setNativeArguments inside process launcher
Change-Id: I4b4db2e5cf6b3ad4d8a39614573564145f125520
Reviewed-by: hjk <hjk@qt.io>
2021-08-09 13:31:24 +00:00