diff options
author | Miikka Heikkinen <miikka.heikkinen@digia.com> | 2010-08-16 13:09:34 (GMT) |
---|---|---|
committer | Miikka Heikkinen <miikka.heikkinen@digia.com> | 2010-08-16 13:58:34 (GMT) |
commit | 7cfc9f2245162944f3d9a29ad73cd93e2bcf197f (patch) | |
tree | 3e8c9a26ed980702ea0f87a25a181bbd773612b7 | |
parent | 881b3bf8212432590d19e2a979577c2a9f3ab80b (diff) | |
download | Qt-7cfc9f2245162944f3d9a29ad73cd93e2bcf197f.zip Qt-7cfc9f2245162944f3d9a29ad73cd93e2bcf197f.tar.gz Qt-7cfc9f2245162944f3d9a29ad73cd93e2bcf197f.tar.bz2 |
Fix QProcessManager destruction
If QProcessManager destructor is ran as part of global static cleanup,
manager thread will most likely be terminated by kernel at that point,
so trying to delete QProcessActives and QProcessMediators will panic as
they will still be active. They can also no longer be properly canceled
as the thread is already gone. In case manager thread has already died,
which implies that process exit is imminent, we simply do nothing and
let the deletion of the main heap at process exit take care of stray
objects.
Task-number: QTBUG-11218
Reviewed-by: Janne Koskinen
-rw-r--r-- | src/corelib/io/qprocess_symbian.cpp | 47 |
1 files changed, 28 insertions, 19 deletions
diff --git a/src/corelib/io/qprocess_symbian.cpp b/src/corelib/io/qprocess_symbian.cpp index af657b2..003e781 100644 --- a/src/corelib/io/qprocess_symbian.cpp +++ b/src/corelib/io/qprocess_symbian.cpp @@ -375,10 +375,9 @@ QProcessActive::QProcessActive() // Nothing to do } -// Called from ProcessManagerThread +// Called from main thread QProcessActive::~QProcessActive() { - Cancel(); process = NULL; pproc = NULL; } @@ -482,10 +481,9 @@ QProcessManagerMediator::QProcessManagerMediator() // Nothing to do } -// Called from ProcessManagerThread +// Called from main thread QProcessManagerMediator::~QProcessManagerMediator() { - Cancel(); processManagerThread.Close(); currentCommand = ENoCommand; currentObserver = NULL; @@ -648,25 +646,36 @@ QProcessManager::QProcessManager() QProcessManager::~QProcessManager() { QPROCESS_DEBUG_PRINT("QProcessManager::~QProcessManager()"); - // Cancel death listening for all child processes - if (mediator) { - QMap<int, QProcessActive *>::Iterator it = children.begin(); - while (it != children.end()) { - // Remove all monitors - QProcessActive *active = it.value(); - mediator->remove(active); - - QPROCESS_DEBUG_PRINT("QProcessManager::~QProcessManager() removed listening for a process"); - ++it; + + // Check if manager thread is still alive. If this destructor is ran as part of global + // static cleanup, manager thread will most likely be terminated by kernel at this point, + // so trying to delete QProcessActives and QProcessMediators will panic as they + // will still be active. They can also no longer be canceled as the thread is already gone. + // In case manager thread has already died, we simply do nothing and let the deletion of + // the main heap at process exit take care of stray objects. + + if (managerThread.Handle() && managerThread.ExitType() == EExitPending) { + // Cancel death listening for all child processes + if (mediator) { + QMap<int, QProcessActive *>::Iterator it = children.begin(); + while (it != children.end()) { + // Remove all monitors + QProcessActive *active = it.value(); + mediator->remove(active); + + QPROCESS_DEBUG_PRINT("QProcessManager::~QProcessManager() removed listening for a process"); + ++it; + } + + // Terminate process manager thread. + mediator->terminate(); + delete mediator; } - // Terminate process manager thread. - mediator->terminate(); - delete mediator; + qDeleteAll(children.values()); + children.clear(); } - qDeleteAll(children.values()); - children.clear(); managerThread.Close(); managerMutex.Close(); } |