diff --git a/src/libs/solutions/tasking/qprocesstask.h b/src/libs/solutions/tasking/qprocesstask.h index 5cec4890e6f..ea75600e521 100644 --- a/src/libs/solutions/tasking/qprocesstask.h +++ b/src/libs/solutions/tasking/qprocesstask.h @@ -11,6 +11,25 @@ namespace Tasking { +// Deleting a running QProcess may block the caller thread up to 30 seconds and issue warnings. +// To avoid these issues we move the running QProcess into a separate thread +// managed by the internal ProcessReaper, instead of deleting it immediately. +// Inside the ProcessReaper's thread we try to finish the process in a most gentle way: +// we call QProcess::terminate() with 500 ms timeout, and if the process is still running +// after the timeout passed, we call QProcess::kill() and wait for the process to finish. +// All these waitings are done is a separate thread, so the main thread doesn't block at all +// when the QProcessTask is destructed. Finally, on application quit, QProcessDeleter::deleteAll() +// should be called to in order to synchronize all the processes being reaped in a separate thread. +// The call to QProcessDeleter::deleteAll() is blocking, but it's unavoidable - sooner or later +// all the processes needs to finish ultimately, so better: block later! +// In this way we terminate running processes in the most safe way and keep the main thread +// responsive. That's a common case when the running QProcess needs to quit quite quicky, +// and the caller thread wants to forget about it, hoping it will be terminated in the most +// sensible way. + +// The implementation of the internal reaper is inspired by the Utils::ProcessReaper taken +// from the QtCreator codebase. + class TASKING_EXPORT QProcessDeleter { public: