forked from qt-creator/qt-creator
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>
This commit is contained in:
@@ -252,15 +252,15 @@ public:
|
||||
: ProcessInterface(processMode), m_token(uniqueToken())
|
||||
{
|
||||
m_handle = LauncherInterface::socket()->registerHandle(token(), processMode);
|
||||
connect(m_handle, &LauncherHandle::errorOccurred,
|
||||
connect(m_handle, &CallerHandle::errorOccurred,
|
||||
this, &ProcessInterface::errorOccurred);
|
||||
connect(m_handle, &LauncherHandle::started,
|
||||
connect(m_handle, &CallerHandle::started,
|
||||
this, &ProcessInterface::started);
|
||||
connect(m_handle, &LauncherHandle::finished,
|
||||
connect(m_handle, &CallerHandle::finished,
|
||||
this, &ProcessInterface::finished);
|
||||
connect(m_handle, &LauncherHandle::readyReadStandardOutput,
|
||||
connect(m_handle, &CallerHandle::readyReadStandardOutput,
|
||||
this, &ProcessInterface::readyReadStandardOutput);
|
||||
connect(m_handle, &LauncherHandle::readyReadStandardError,
|
||||
connect(m_handle, &CallerHandle::readyReadStandardError,
|
||||
this, &ProcessInterface::readyReadStandardError);
|
||||
}
|
||||
~ProcessLauncherImpl() override
|
||||
@@ -318,7 +318,7 @@ private:
|
||||
|
||||
const uint m_token = 0;
|
||||
// Lives in launcher's thread.
|
||||
LauncherHandle *m_handle = nullptr;
|
||||
CallerHandle *m_handle = nullptr;
|
||||
};
|
||||
|
||||
void ProcessLauncherImpl::cancel()
|
||||
@@ -456,6 +456,9 @@ QtcProcess::QtcProcess(ProcessImpl processImpl, ProcessMode processMode, QObject
|
||||
Q_UNUSED(qProcessProcessErrorMeta)
|
||||
}
|
||||
|
||||
QtcProcess::QtcProcess(ProcessImpl processImpl, QObject *parent)
|
||||
: QtcProcess(processImpl, ProcessMode::Reader, parent) {}
|
||||
|
||||
QtcProcess::QtcProcess(ProcessMode processMode, QObject *parent)
|
||||
: QtcProcess(defaultProcessImpl(), processMode, parent) {}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user