summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorisanae <14251494+isanae@users.noreply.github.com>2019-12-15 21:56:50 -0500
committerisanae <14251494+isanae@users.noreply.github.com>2019-12-15 21:56:50 -0500
commitf3c5cebb6e9262625105d4339a54a810d7816811 (patch)
treef8a241de842327e80581b504a042f93d79e4d0e8 /src
parentdcf88361d49da262acaac335d1317a5d7ef42ded (diff)
fixed exiting before QThread joins when pressing the X twice
Diffstat (limited to 'src')
-rw-r--r--src/mainwindow.cpp21
-rw-r--r--src/processrunner.cpp31
-rw-r--r--src/shared/util.cpp11
-rw-r--r--src/shared/util.h1
4 files changed, 46 insertions, 18 deletions
diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp
index a29ea8ab..d1578d85 100644
--- a/src/mainwindow.cpp
+++ b/src/mainwindow.cpp
@@ -1317,18 +1317,25 @@ void MainWindow::closeEvent(QCloseEvent* event)
//
// for 2), the settings have been saved and the window can just close
- if (ModOrganizerExiting()) {
+ if (ModOrganizerCanCloseNow()) {
// the user has confirmed if necessary and all settings have been saved,
// just close it
QMainWindow::closeEvent(event);
- } else {
- // never close the window because settings might need to be changed
- event->ignore();
+ return;
+ }
- // start the process of exiting, which may require confirmation by calling
- // canExit(), among other things
- ExitModOrganizer();
+ if (ModOrganizerExiting()) {
+ // ignore repeated attempts
+ event->ignore();
+ return;
}
+
+ // never close the window because settings might need to be changed
+ event->ignore();
+
+ // start the process of exiting, which may require confirmation by calling
+ // canExit(), among other things
+ ExitModOrganizer();
}
bool MainWindow::canExit()
diff --git a/src/processrunner.cpp b/src/processrunner.cpp
index 19aae632..aead42d1 100644
--- a/src/processrunner.cpp
+++ b/src/processrunner.cpp
@@ -225,7 +225,7 @@ const std::chrono::milliseconds Infinite(-1);
//
std::optional<ProcessRunner::Results> timedWait(
HANDLE handle, DWORD pid, UILocker::Session& ls,
- std::chrono::milliseconds wait)
+ std::chrono::milliseconds wait, std::atomic<bool>& interrupt)
{
using namespace std::chrono;
@@ -234,7 +234,7 @@ std::optional<ProcessRunner::Results> timedWait(
start = high_resolution_clock::now();
}
- for (;;) {
+ while (!interrupt) {
// wait for a very short while, allows for processing events below
const auto r = singleWait(handle, pid);
@@ -286,10 +286,13 @@ std::optional<ProcessRunner::Results> timedWait(
}
}
}
+
+ log::debug("waiting for {} interrupted", pid);
+ return ProcessRunner::ForceUnlocked;
}
ProcessRunner::Results waitForProcessesThreadImpl(
- HANDLE job, UILocker::Session& ls)
+ HANDLE job, UILocker::Session& ls, std::atomic<bool>& interrupt)
{
using namespace std::chrono;
@@ -301,7 +304,7 @@ ProcessRunner::Results waitForProcessesThreadImpl(
const milliseconds defaultWait(50);
auto wait = defaultWait;
- for (;;) {
+ while (!interrupt) {
auto ip = getInterestingProcess(job);
if (!ip.handle) {
// nothing to wait on
@@ -325,7 +328,7 @@ ProcessRunner::Results waitForProcessesThreadImpl(
wait = Infinite;
}
- const auto r = timedWait(ip.handle.get(), ip.p.pid(), ls, wait);
+ const auto r = timedWait(ip.handle.get(), ip.p.pid(), ls, wait, interrupt);
if (r) {
if (*r == ProcessRunner::Results::Completed) {
// process completed, check another one, reset the wait time to find
@@ -344,9 +347,10 @@ ProcessRunner::Results waitForProcessesThreadImpl(
}
void waitForProcessesThread(
- ProcessRunner::Results& result, HANDLE job, UILocker::Session& ls)
+ ProcessRunner::Results& result, HANDLE job, UILocker::Session& ls,
+ std::atomic<bool>& interrupt)
{
- result = waitForProcessesThreadImpl(job, ls);
+ result = waitForProcessesThreadImpl(job, ls, interrupt);
ls.unlock();
}
@@ -379,9 +383,11 @@ ProcessRunner::Results waitForProcesses(
}
auto results = ProcessRunner::Running;
+ std::atomic<bool> interrupt(false);
auto* t = QThread::create(
- waitForProcessesThread, std::ref(results), job.get(), std::ref(ls));
+ waitForProcessesThread,
+ std::ref(results), job.get(), std::ref(ls), std::ref(interrupt));
QEventLoop events;
QObject::connect(t, &QThread::finished, [&]{
@@ -391,6 +397,11 @@ ProcessRunner::Results waitForProcesses(
t->start();
events.exec();
+ if (t->isRunning()) {
+ interrupt = true;
+ t->wait();
+ }
+
delete t;
return results;
@@ -861,7 +872,7 @@ ProcessRunner::Results ProcessRunner::waitForAllUSVFSProcessesWithLock(
auto r = Error;
withLock([&](auto& ls) {
- for (;;) {
+ for (;;) {
const auto processes = getRunningUSVFSProcesses();
if (processes.empty()) {
break;
@@ -878,7 +889,7 @@ ProcessRunner::Results ProcessRunner::waitForAllUSVFSProcessesWithLock(
}
r = Completed;
- });
+ });
return r;
}
diff --git a/src/shared/util.cpp b/src/shared/util.cpp
index 32eb825c..baceddeb 100644
--- a/src/shared/util.cpp
+++ b/src/shared/util.cpp
@@ -294,6 +294,7 @@ QString getUsvfsVersionString()
static bool g_exiting = false;
+static bool g_canClose = false;
MainWindow* findMainWindow()
{
@@ -312,6 +313,9 @@ bool ExitModOrganizer(ExitFlags e)
return true;
}
+ g_exiting = true;
+ MOBase::Guard g([&]{ g_exiting = false; });
+
if (!e.testFlag(Exit::Force)) {
if (auto* mw=findMainWindow()) {
if (!mw->canExit()) {
@@ -320,7 +324,7 @@ bool ExitModOrganizer(ExitFlags e)
}
}
- g_exiting = true;
+ g_canClose = true;
const int code = (e.testFlag(Exit::Restart) ? RestartExitCode : 0);
qApp->exit(code);
@@ -328,6 +332,11 @@ bool ExitModOrganizer(ExitFlags e)
return true;
}
+bool ModOrganizerCanCloseNow()
+{
+ return g_canClose;
+}
+
bool ModOrganizerExiting()
{
return g_exiting;
diff --git a/src/shared/util.h b/src/shared/util.h
index e87244b6..e8a58549 100644
--- a/src/shared/util.h
+++ b/src/shared/util.h
@@ -65,6 +65,7 @@ Q_DECLARE_OPERATORS_FOR_FLAGS(ExitFlags);
bool ExitModOrganizer(ExitFlags e=Exit::Normal);
bool ModOrganizerExiting();
+bool ModOrganizerCanCloseNow();
void ResetExitFlag();
#endif // UTIL_H