diff --git a/library/Console-posix.cpp b/library/Console-posix.cpp index 9c244de10..a2f59077d 100644 --- a/library/Console-posix.cpp +++ b/library/Console-posix.cpp @@ -730,8 +730,7 @@ Console::Console() } Console::~Console() { - if(inited) - shutdown(); + assert(!inited); if(wlock) delete wlock; if(d) @@ -768,11 +767,6 @@ bool Console::shutdown(void) if(!d) return true; lock_guard g(*wlock); - if(d->rawmode) - d->disable_raw(); - d->print("\n"); - inited = false; - // kill the thing close(d->exit_pipe[1]); return true; } @@ -854,8 +848,16 @@ int Console::lineedit(const std::string & prompt, std::string & output, CommandH { lock_guard g(*wlock); int ret = -2; - if(inited) + if(inited) { ret = d->lineedit(prompt,output,wlock,ch); + if (ret == -2) { + // kill the thing + if(d->rawmode) + d->disable_raw(); + d->print("\n"); + inited = false; + } + } return ret; } diff --git a/library/Console-windows.cpp b/library/Console-windows.cpp index 3caacd924..f3771f4ff 100644 --- a/library/Console-windows.cpp +++ b/library/Console-windows.cpp @@ -285,7 +285,10 @@ namespace DFHack INPUT_RECORD rec; DWORD count; lock->unlock(); - ReadConsoleInputA(console_in, &rec, 1, &count); + if (ReadConsoleInputA(console_in, &rec, 1, &count) != 0) { + lock->lock(); + return -2; + } lock->lock(); if (rec.EventType != KEY_EVENT || !rec.Event.KeyEvent.bKeyDown) continue; diff --git a/library/Core.cpp b/library/Core.cpp index fccf3fa0e..d584cb891 100644 --- a/library/Core.cpp +++ b/library/Core.cpp @@ -130,6 +130,7 @@ struct Core::Private Core::Cond core_cond; thread::id df_suspend_thread; int df_suspend_depth; + std::thread iothread; Private() { df_suspend_depth = 0; @@ -1476,6 +1477,12 @@ void fIOthread(void * iodata) } } +Core::~Core() +{ + if (d->iothread.joinable()) + con.shutdown(); + delete d; +} Core::Core() : d{new Private}, @@ -1739,12 +1746,12 @@ bool Core::Init() { cerr << "Starting IO thread.\n"; // create IO thread - new thread(fIOthread, (void *) temp); + d->iothread = std::thread{fIOthread, (void*)temp}; } else { - cerr << "Starting dfhack.init thread.\n"; - new thread(fInitthread, (void *) temp); + std::cerr << "Starting dfhack.init thread.\n"; + d->iothread = std::thread{fInitthread, (void*)temp}; } cerr << "Starting DF input capture thread.\n"; @@ -2339,9 +2346,14 @@ void Core::onStateChange(color_ostream &out, state_change_event event) handleLoadAndUnloadScripts(out, event); } -// FIXME: needs to terminate the IO threads and properly dismantle all the machinery involved. int Core::Shutdown ( void ) { + // Make sure the console thread shutdowns before clean up to avoid any + // unlikely data races. + if (d->iothread.joinable()) { + con.shutdown(); + d->iothread.join(); + } if(errorstate) return true; errorstate = 1; @@ -2358,7 +2370,6 @@ int Core::Shutdown ( void ) } allModules.clear(); memset(&(s_mods), 0, sizeof(s_mods)); - con.shutdown(); return -1; } diff --git a/library/include/Core.h b/library/include/Core.h index a8bbb9c41..6e3bd718e 100644 --- a/library/include/Core.h +++ b/library/include/Core.h @@ -198,6 +198,7 @@ namespace DFHack DFHack::Console con; Core(); + ~Core(); struct Private; Private *d;