QtcProcess: Ensure we don't delete the process from handlers

Guard that we don't delete the QtcProcess directly from
inside its handlers.

This helps in detecting wrong usage of QtcProcess.

Change-Id: Ia5b154b3e1f827d579910ebe81ae230fc797c377
Reviewed-by: Christian Stenger <christian.stenger@qt.io>
This commit is contained in:
Jarek Kobus
2022-04-04 16:35:26 +02:00
parent 97132cf7f0
commit a717ff71f4

View File

@@ -528,7 +528,7 @@ public:
m_process->setParent(this); m_process->setParent(this);
connect(m_process.get(), &ProcessInterface::started, connect(m_process.get(), &ProcessInterface::started,
q, &QtcProcess::emitStarted); this, &QtcProcessPrivate::emitStarted);
connect(m_process.get(), &ProcessInterface::finished, connect(m_process.get(), &ProcessInterface::finished,
this, &QtcProcessPrivate::slotFinished); this, &QtcProcessPrivate::slotFinished);
connect(m_process.get(), &ProcessInterface::errorOccurred, connect(m_process.get(), &ProcessInterface::errorOccurred,
@@ -543,14 +543,14 @@ public:
{ {
m_stdOut.append(m_process->readAllStandardOutput()); m_stdOut.append(m_process->readAllStandardOutput());
m_hangTimerCount = 0; m_hangTimerCount = 0;
emit q->readyReadStandardOutput(); emitReadyReadStandardOutput();
} }
void handleReadyReadStandardError() void handleReadyReadStandardError()
{ {
m_stdErr.append(m_process->readAllStandardError()); m_stdErr.append(m_process->readAllStandardError());
m_hangTimerCount = 0; m_hangTimerCount = 0;
emit q->readyReadStandardError(); emitReadyReadStandardError();
} }
CommandLine fullCommandLine() const CommandLine fullCommandLine() const
@@ -590,7 +590,11 @@ public:
void handleError(QProcess::ProcessError error); void handleError(QProcess::ProcessError error);
void clearForRun(); void clearForRun();
void emitStarted();
void emitFinished();
void emitErrorOccurred(QProcess::ProcessError error); void emitErrorOccurred(QProcess::ProcessError error);
void emitReadyReadStandardOutput();
void emitReadyReadStandardError();
ProcessResult interpretExitCode(int exitCode); ProcessResult interpretExitCode(int exitCode);
@@ -606,7 +610,18 @@ public:
StartFailure m_startFailure = NoFailure; StartFailure m_startFailure = NoFailure;
bool m_timeOutMessageBoxEnabled = false; bool m_timeOutMessageBoxEnabled = false;
bool m_waitingForUser = false; bool m_waitingForUser = false;
class Guard {
public:
Guard(int &guard) : m_guard(guard) { ++guard; }
~Guard() { --m_guard; }
private:
int &m_guard;
}; };
int m_callStackGuard = 0;
};
#define CALL_STACK_GUARD() Guard guard(m_callStackGuard)
void QtcProcessPrivate::clearForRun() void QtcProcessPrivate::clearForRun()
{ {
@@ -692,6 +707,7 @@ QtcProcess::QtcProcess(QObject *parent)
QtcProcess::~QtcProcess() QtcProcess::~QtcProcess()
{ {
QTC_CHECK(d->m_callStackGuard == 0);
delete d; delete d;
} }
@@ -703,7 +719,6 @@ void QtcProcess::emitStarted()
void QtcProcess::emitFinished() void QtcProcess::emitFinished()
{ {
emit finished(); emit finished();
emit done();
} }
void QtcProcess::setProcessInterface(ProcessInterface *interface) void QtcProcess::setProcessInterface(ProcessInterface *interface)
@@ -1607,7 +1622,7 @@ void QtcProcessPrivate::slotTimeout()
void QtcProcessPrivate::slotFinished() void QtcProcessPrivate::slotFinished()
{ {
handleFinished(m_process->exitCode(), m_process->exitStatus()); handleFinished(m_process->exitCode(), m_process->exitStatus());
q->emitFinished(); emitFinished();
} }
void QtcProcessPrivate::handleFinished(int exitCode, QProcess::ExitStatus status) void QtcProcessPrivate::handleFinished(int exitCode, QProcess::ExitStatus status)
@@ -1648,13 +1663,39 @@ void QtcProcessPrivate::handleError(QProcess::ProcessError error)
emitErrorOccurred(error); emitErrorOccurred(error);
} }
void QtcProcessPrivate::emitStarted()
{
CALL_STACK_GUARD();
q->emitStarted();
}
void QtcProcessPrivate::emitFinished()
{
CALL_STACK_GUARD();
q->emitFinished();
emit q->done();
}
void QtcProcessPrivate::emitErrorOccurred(QProcess::ProcessError error) void QtcProcessPrivate::emitErrorOccurred(QProcess::ProcessError error)
{ {
CALL_STACK_GUARD();
emit q->errorOccurred(error); emit q->errorOccurred(error);
if (error == QProcess::FailedToStart) if (error == QProcess::FailedToStart)
emit q->done(); emit q->done();
} }
void QtcProcessPrivate::emitReadyReadStandardOutput()
{
CALL_STACK_GUARD();
emit q->readyReadStandardOutput();
}
void QtcProcessPrivate::emitReadyReadStandardError()
{
CALL_STACK_GUARD();
emit q->readyReadStandardError();
}
} // namespace Utils } // namespace Utils
#include "qtcprocess.moc" #include "qtcprocess.moc"