Commit Graph

32 Commits

Author SHA1 Message Date
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
Jarek Kobus
8fa1a1f587 Handle belowNormalPriority inside process launcher on Windows
Remove setCreateProcessArgumentModifier() from the ProcessInterface
API and replace it with belowNormalPriority flag.

Change-Id: I6bcb92e56c3a68af7fa3e3a1c8b8eb13e3a2e5a7
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: hjk <hjk@qt.io>
2021-08-09 13:23:37 +00:00
Jarek Kobus
25f585227f Refactor openMode/keepWriteChannelOpen/closeWriteChannel
Change-Id: I4090533875ce1da864b6f8554ce59dbc1392a142
Reviewed-by: hjk <hjk@qt.io>
2021-08-09 07:51:26 +00:00
Jarek Kobus
81cbb0a33c Return the write size
Amends 535d312e93

Change-Id: Icdc0eec0d017a65b64b6c20233c67caf2e81c16a
Reviewed-by: Jarek Kobus <jaroslaw.kobus@qt.io>
2021-08-07 00:04:49 +00:00
Jarek Kobus
535d312e93 Implement writing to process inside process launcher
Change-Id: I7321a941024d431cc52b3f6ae0b1ef38d851db8c
Reviewed-by: hjk <hjk@qt.io>
2021-08-06 14:32:21 +00:00
Jarek Kobus
e41b6a0a29 Make process reusable when killing the running one
Try to mimic the behavior of QProcess inside process launcher
as much as possible. After calling QtcProcess::kill() we send
StopProcessPacket to the process launcher - when we receive
it there we start reaping of the process itself and report
back the finished packet with a failure.

Remove canceled state from the LanucherHandle, as after
canceling the process we still need to handle the finished
(or others) signals - like in case of QProcess.

Change-Id: Id66b06449de06675a0ab6778e93e9782afea09d4
Reviewed-by: hjk <hjk@qt.io>
2021-08-05 18:53:41 +00:00
Jarek Kobus
ba037a707e Implement readyRead inside process launcher
Change-Id: I3a27edef2307053b8c4c7d8f1dbf7e0400e27416
Reviewed-by: hjk <hjk@qt.io>
2021-08-05 18:53:22 +00:00
Jarek Kobus
48c1f56ebe Refactor waiting for logic
Instead of waiting for certain state we wait for
certain signal to be placed into the buffer.
No need for m_finished flag anymore, since we are
only interesting if the buffer contains the finished
signal. This will enable to implement waiting for
ready read properly, since no state is changed
in this case.

Change-Id: I4209da385b2e37de6f1897357e35c0ed0c9e4096
Reviewed-by: hjk <hjk@qt.io>
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
2021-08-05 14:50:49 +00:00
Jarek Kobus
17f907da9b Implement setStandardInputFile() in ProcessLauncherImpl
Change-Id: I4d77c86ecb750573ce5421ca7300eb27f9f76108
Reviewed-by: hjk <hjk@qt.io>
2021-08-02 13:48:46 +00:00
Jarek Kobus
eca63813d5 Simplify waitForState() implementation
Change-Id: I7bbb06411d0c30ab931cb17b5a1b5940b51e978e
Reviewed-by: hjk <hjk@qt.io>
2021-08-02 07:50:16 +00:00
Jarek Kobus
7e747e25bb Pipe readyRead() through the CallerHandle
In this way the output and error channels
get handled while waitingFor* is being executed.

Change-Id: I8d3d81bd99fcfb7ddea7e98337e859446380055f
Reviewed-by: hjk <hjk@qt.io>
2021-07-16 09:55:48 +00:00
Jarek Kobus
f7cf48bc28 Refactor process launcher
Move launcher process into a separate thread.
Implement blocking API by using wait condition
on the caller's side. Replay all collected
signals from the launcher's thread when leaving
waitingFor* state. In case we were not waiting
for anything deliver the signals asynchronously
from launcher's thread to the caller's thread.

Change-Id: Id44fe5f7ceaac407004984a1dfb6ea65f197d297
Reviewed-by: hjk <hjk@qt.io>
2021-07-16 07:52:58 +00:00
Jarek Kobus
d8286adc7c Implement ProcessLauncher::processId()
Implement the reply confirmation for the started signal.
After qtcreator_processlauncher starts a new process
we connect to its started() signal and post a reply through
the socket to the LauncherInterface with the information about
the new PID. ProcessLauncherImpl now emits the started signal
with a delay, just after the confirmation has been received.

Change-Id: I2689e8e97b17466bd1f6b32c01909c12d80fcdef
Reviewed-by: hjk <hjk@qt.io>
2021-07-12 15:13:03 +00:00
Jarek Kobus
58d00f37d4 Initial import of processlauncher copy from qbs project
Change-Id: I9d646dd1a820e4e69c808998d9f12ff2f5dabe6d
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: hjk <hjk@qt.io>
2021-07-08 12:12:10 +00:00