fix(library/module): potential deadlock when child thread threw an exception
Signed-off-by: Leonardo de Moura <leonardo@microsoft.com>
This commit is contained in:
parent
25b822b1c7
commit
7124866a4f
1 changed files with 8 additions and 6 deletions
|
@ -358,23 +358,29 @@ struct import_modules_fn {
|
||||||
return;
|
return;
|
||||||
std::vector<std::unique_ptr<interruptible_thread>> extra_threads;
|
std::vector<std::unique_ptr<interruptible_thread>> extra_threads;
|
||||||
std::vector<std::unique_ptr<exception>> thread_exceptions(m_num_threads - 1);
|
std::vector<std::unique_ptr<exception>> thread_exceptions(m_num_threads - 1);
|
||||||
|
atomic<int> failed_thread_idx(-1); // >= 0 if error
|
||||||
for (unsigned i = 0; i < m_num_threads - 1; i++) {
|
for (unsigned i = 0; i < m_num_threads - 1; i++) {
|
||||||
extra_threads.push_back(std::unique_ptr<interruptible_thread>(new interruptible_thread([=, &thread_exceptions]() {
|
extra_threads.push_back(std::unique_ptr<interruptible_thread>(new interruptible_thread([=, &thread_exceptions, &failed_thread_idx]() {
|
||||||
try {
|
try {
|
||||||
while (auto t = next_task()) {
|
while (auto t = next_task()) {
|
||||||
(*t)(m_senv);
|
(*t)(m_senv);
|
||||||
}
|
}
|
||||||
m_asynch_cv.notify_all();
|
m_asynch_cv.notify_all();
|
||||||
} catch (exception ex) {
|
} catch (exception & ex) {
|
||||||
thread_exceptions[i].reset(ex.clone());
|
thread_exceptions[i].reset(ex.clone());
|
||||||
|
failed_thread_idx = i;
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
thread_exceptions[i].reset(new exception("module import thread failed for unknown reasons"));
|
thread_exceptions[i].reset(new exception("module import thread failed for unknown reasons"));
|
||||||
|
failed_thread_idx = i;
|
||||||
}
|
}
|
||||||
})));
|
})));
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
while (auto t = next_task()) {
|
while (auto t = next_task()) {
|
||||||
(*t)(m_senv);
|
(*t)(m_senv);
|
||||||
|
int idx = failed_thread_idx;
|
||||||
|
if (idx >= 0)
|
||||||
|
thread_exceptions[idx]->rethrow();
|
||||||
}
|
}
|
||||||
m_asynch_cv.notify_all();
|
m_asynch_cv.notify_all();
|
||||||
for (auto & th : extra_threads)
|
for (auto & th : extra_threads)
|
||||||
|
@ -386,10 +392,6 @@ struct import_modules_fn {
|
||||||
th->join();
|
th->join();
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
for (auto const & ex : thread_exceptions) {
|
|
||||||
if (ex.get())
|
|
||||||
ex->rethrow();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
environment process_delayed_tasks() {
|
environment process_delayed_tasks() {
|
||||||
|
|
Loading…
Reference in a new issue