use_dll: fixes to parallel compilation

— No longer call std::exit() from threads when compilation fails, that function
  is marked as not thread-safe under GNU/Linux; and it leads to deadlocks under
  Windows. Rather store the list of failed objects, and exit with a message and
  an error code from the main thread when that list is not empty at the end of
  preprocessing.
– Fix the condition used for waiting until all compilation threads finish;
  checking that the queue is empty is not enough, since a compilation may be
  ongoing. So also track objects whose compilation is ongoing.
master
Sébastien Villemot 2022-12-20 14:47:32 +01:00
parent f349e22f4c
commit 21fcfa7758
No known key found for this signature in database
GPG Key ID: 2CECE9350ECEBE4A
2 changed files with 25 additions and 9 deletions

View File

@ -44,7 +44,7 @@
condition_variable_any ModelTree::mex_compilation_cv;
mutex ModelTree::mex_compilation_mut;
vector<tuple<filesystem::path, set<filesystem::path>, string>> ModelTree::mex_compilation_queue;
set<filesystem::path> ModelTree::mex_compilation_done;
set<filesystem::path> ModelTree::mex_compilation_ongoing, ModelTree::mex_compilation_done, ModelTree::mex_compilation_failed;
vector<jthread> ModelTree::mex_compilation_workers;
void
@ -1955,6 +1955,7 @@ ModelTree::initializeMEXCompilationWorkers(int numworkers)
output = get<0>(*it);
cmd = get<2>(*it);
mex_compilation_queue.erase(it);
mex_compilation_ongoing.insert(output);
return true;
}
return false;
@ -1964,13 +1965,13 @@ ModelTree::initializeMEXCompilationWorkers(int numworkers)
if (mex_compilation_cv.wait(lk, stoken, pick_job))
{
lk.unlock();
if (system(cmd.c_str()))
{
cerr << "Compilation failed" << endl;
exit(EXIT_FAILURE);
}
int r { system(cmd.c_str()) };
lk.lock();
mex_compilation_done.insert(output);
mex_compilation_ongoing.erase(output);
if (r)
mex_compilation_failed.insert(output);
else
mex_compilation_done.insert(output);
/* The object just compiled may be a prerequisite for several
other objects, so notify all waiting workers. Also needed to
notify the main thread when in
@ -1984,7 +1985,18 @@ void
ModelTree::waitForMEXCompilationWorkers()
{
unique_lock<mutex> lk {mex_compilation_mut};
mex_compilation_cv.wait(lk, [] { return mex_compilation_queue.empty(); });
mex_compilation_cv.wait(lk, [] {
return (mex_compilation_queue.empty() && mex_compilation_ongoing.empty())
|| !mex_compilation_failed.empty(); });
if (!mex_compilation_failed.empty())
{
cerr << "Compilation failed for: ";
for (const auto &p : mex_compilation_failed)
cerr << p.string() << " ";
cerr << endl;
lk.unlock(); // So that threads can process their stoken
exit(EXIT_FAILURE);
}
}
void

View File

@ -439,8 +439,12 @@ private:
/* Object/MEX files waiting to be compiled (with their prerequisites as 2nd
element and compilation command as the 3rd element) */
static vector<tuple<filesystem::path, set<filesystem::path>, string>> mex_compilation_queue;
// Object/MEX files already compiled
// Object/MEX files in the process of being compiled
static set<filesystem::path> mex_compilation_ongoing;
// Object/MEX files already compiled successfully
static set<filesystem::path> mex_compilation_done;
// Object/MEX files whose compilation failed
static set<filesystem::path> mex_compilation_failed;
/* Compute a pseudo-Jacobian whose all elements are either zero or one,
depending on whether the variable symbolically appears in the equation. If