summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJoerg Bornemann <joerg.bornemann@theqtcompany.com>2015-06-18 17:52:36 +0200
committerJoerg Bornemann <joerg.bornemann@theqtcompany.com>2015-06-19 08:09:56 +0000
commit0d4aa3809ea4bdfb25a07ff85004b05ffb0e39bb (patch)
treed31156ed7f014aefc8072596be4cae58074d2384
parenta5266e57f47bfb769e54a6cedef067df6056ca6d (diff)
fix occasional hang on exit
We occasionally encountered a hang on exit in ~IoCompletionPort on QThread::wait(). We must not use Q_GLOBAL_STATIC for IoCompletionPort, because it's a QThread. We will enter undefined terrain after QCoreApplication is gone. We now properly destroy IoCompletionPort in ~Application. Task-number: QTCREATORBUG-14600 Change-Id: I067d50ec6759f5438cf47b2ba01f17a402ab8910 Reviewed-by: Oswald Buddenhagen <oswald.buddenhagen@theqtcompany.com>
-rw-r--r--src/app/application.cpp7
-rw-r--r--src/app/application.h2
-rw-r--r--src/jomlib/iocompletionport.cpp15
-rw-r--r--src/jomlib/iocompletionport.h8
-rw-r--r--src/jomlib/process.cpp13
5 files changed, 36 insertions, 9 deletions
diff --git a/src/app/application.cpp b/src/app/application.cpp
index a171928..54baedb 100644
--- a/src/app/application.cpp
+++ b/src/app/application.cpp
@@ -19,6 +19,8 @@
****************************************************************************/
#include "application.h"
+#include <iocompletionport.h>
+
#include <QtCore/QDebug>
#include <QtCore/QFileInfo>
#include <QtCore/QSet>
@@ -76,6 +78,11 @@ Application::Application(int &argc, char **argv)
m_bIsSubJOM = NMakeFile::isSubJOM(exeName);
}
+Application::~Application()
+{
+ IoCompletionPort::destroyInstance();
+}
+
void Application::exit(int exitCode)
{
QCoreApplication::exit(exitCode);
diff --git a/src/app/application.h b/src/app/application.h
index 8bb6b26..1b3618b 100644
--- a/src/app/application.h
+++ b/src/app/application.h
@@ -32,6 +32,8 @@ public:
static Application *instance() { return static_cast<Application*>(QCoreApplication::instance()); }
Application(int &argc, char **argv);
+ ~Application();
+
const bool isSubJOM() const { return m_bIsSubJOM; }
public slots:
diff --git a/src/jomlib/iocompletionport.cpp b/src/jomlib/iocompletionport.cpp
index 2ea3e88..e2f0d3a 100644
--- a/src/jomlib/iocompletionport.cpp
+++ b/src/jomlib/iocompletionport.cpp
@@ -22,6 +22,8 @@
namespace NMakeFile {
+IoCompletionPort *IoCompletionPort::m_instance = 0;
+
IoCompletionPort::IoCompletionPort()
: hPort(INVALID_HANDLE_VALUE)
{
@@ -41,6 +43,19 @@ IoCompletionPort::~IoCompletionPort()
CloseHandle(hPort);
}
+IoCompletionPort *IoCompletionPort::instance()
+{
+ if (!m_instance)
+ m_instance = new IoCompletionPort;
+ return m_instance;
+}
+
+void IoCompletionPort::destroyInstance()
+{
+ delete m_instance;
+ m_instance = 0;
+}
+
void IoCompletionPort::registerObserver(IoCompletionPortObserver *observer, HANDLE hFile)
{
HANDLE hIOCP = CreateIoCompletionPort(hFile, hPort, reinterpret_cast<ULONG_PTR>(observer), 0);
diff --git a/src/jomlib/iocompletionport.h b/src/jomlib/iocompletionport.h
index 17b44bf..91aea49 100644
--- a/src/jomlib/iocompletionport.h
+++ b/src/jomlib/iocompletionport.h
@@ -37,8 +37,8 @@ public:
class IoCompletionPort : protected QThread
{
public:
- IoCompletionPort();
- ~IoCompletionPort();
+ static IoCompletionPort *instance();
+ static void destroyInstance();
void registerObserver(IoCompletionPortObserver *notifier, HANDLE hFile);
void unregisterObserver(IoCompletionPortObserver *notifier);
@@ -47,6 +47,10 @@ protected:
void run();
private:
+ IoCompletionPort();
+ ~IoCompletionPort();
+
+ static IoCompletionPort *m_instance;
HANDLE hPort;
QSet<IoCompletionPortObserver *> observers;
QMutex mutex;
diff --git a/src/jomlib/process.cpp b/src/jomlib/process.cpp
index 5332c22..224bf9a 100644
--- a/src/jomlib/process.cpp
+++ b/src/jomlib/process.cpp
@@ -47,7 +47,6 @@
namespace NMakeFile {
-Q_GLOBAL_STATIC(IoCompletionPort, iocp)
Q_GLOBAL_STATIC(QElapsedTimer, runtime)
struct Pipe
@@ -161,8 +160,8 @@ Process::Process(QObject *parent)
Process::~Process()
{
- iocp()->unregisterObserver(&d->stdoutChannel);
- iocp()->unregisterObserver(&d->stderrChannel);
+ IoCompletionPort::instance()->unregisterObserver(&d->stdoutChannel);
+ IoCompletionPort::instance()->unregisterObserver(&d->stderrChannel);
if (m_state == Running)
qWarning("Process: destroyed while process still running.");
@@ -362,8 +361,8 @@ void Process::start(const QString &commandLine)
if (!setupPipe(d->stderrPipe, &sa, OutputPipe))
qFatal("Cannot setup pipe for stderr.");
- iocp()->registerObserver(&d->stdoutChannel, d->stdoutPipe.hRead);
- iocp()->registerObserver(&d->stderrChannel, d->stderrPipe.hRead);
+ IoCompletionPort::instance()->registerObserver(&d->stdoutChannel, d->stdoutPipe.hRead);
+ IoCompletionPort::instance()->registerObserver(&d->stderrChannel, d->stderrPipe.hRead);
if (!d->startRead()) {
m_state = NotRunning;
emit error(FailedToStart);
@@ -429,8 +428,8 @@ void Process::onProcessFinished()
return;
d->deathNotifier.setEnabled(false);
- iocp()->unregisterObserver(&d->stdoutChannel);
- iocp()->unregisterObserver(&d->stderrChannel);
+ IoCompletionPort::instance()->unregisterObserver(&d->stdoutChannel);
+ IoCompletionPort::instance()->unregisterObserver(&d->stderrChannel);
safelyCloseHandle(d->stdoutPipe.hRead);
safelyCloseHandle(d->stderrPipe.hRead);
safelyCloseHandle(d->hProcess);