diff --git a/include/hobbes/eval/cmodule.H b/include/hobbes/eval/cmodule.H index 037d4e2c..b79a024b 100644 --- a/include/hobbes/eval/cmodule.H +++ b/include/hobbes/eval/cmodule.H @@ -5,6 +5,8 @@ #include #include +#include + namespace hobbes { class cc; @@ -17,7 +19,9 @@ void pushModuleDir(const std::string&); void popModuleDir(); // compile a whole module into a cc context -void compile(cc*, const ModulePtr& m); +// once stopFn() is true, the compilation stops prematurely, +// cc is not valid anymore, all you can do is to destroy it +void compile(cc*, const ModulePtr& m, std::function stopFn=[] { return false; }); // set language options, display language options using OptDescs = std::map; diff --git a/lib/hobbes/eval/cmodule.C b/lib/hobbes/eval/cmodule.C index 17e99cb8..998b0760 100644 --- a/lib/hobbes/eval/cmodule.C +++ b/lib/hobbes/eval/cmodule.C @@ -794,8 +794,11 @@ void compile(const ModulePtr &, cc *, const MSafePragmaDef *mpd) { // for now, just treat each definition independently and stick it in the input // environment // (this disallows things like mutual recursion) -void compile(cc *e, const ModulePtr &m) { +void compile(cc *e, const ModulePtr &m, std::function stopFn) { for (const auto& tmd : m->definitions()) { + if (stopFn()) { + return; + } auto md = applyTypeDefns(m, e, tmd); if (const MImport *imp = is(md)) { @@ -821,6 +824,9 @@ void compile(cc *e, const ModulePtr &m) { // compile unsafe pragma for (const auto& tmd : m->definitions()) { + if (stopFn()) { + return; + } if (const MUnsafePragmaDef *vpd = is(tmd)) { compile(m, e, vpd); } @@ -828,6 +834,9 @@ void compile(cc *e, const ModulePtr &m) { // compile safe pragma for (const auto& tmd : m->definitions()) { + if (stopFn()) { + return; + } if (const MSafePragmaDef *vpd = is(tmd)) { compile(m, e, vpd); } @@ -835,6 +844,9 @@ void compile(cc *e, const ModulePtr &m) { // generate unsafe transitive closure for (const auto& tmd : m->definitions()) { + if (stopFn()) { + return; + } if (const MVarDef *vd = is(tmd)) { switchOf(vd->varExpr(), buildTransitiveUnsafePragmaClosure(*vd)); } diff --git a/test/Spawn.C b/test/Spawn.C index 3fe1e93b..0192c7a5 100644 --- a/test/Spawn.C +++ b/test/Spawn.C @@ -27,11 +27,6 @@ void startChild(int t, hobbes::proc &p) { }); } -bool hasProcessExited(pid_t pid) { - const std::string procDir = "/proc/" + std::to_string(pid); - return !exists(procDir); -} - bool msgInException(const std::exception &e, const std::string &msg) { return std::string(e.what()).find(msg) != std::string::npos; } @@ -40,7 +35,7 @@ const char *const KEY = "HOBBES_LOADING_TIMEOUT_IN_SECS"; } // namespace TEST(Spawn, TimeoutKill) { - hobbes::proc p; + hobbes::proc p{}; hobbes::str::env(KEY, "1"); // this may affect other tests' behavior bool exp = false; try { @@ -50,11 +45,11 @@ TEST(Spawn, TimeoutKill) { EXPECT_TRUE(msgInException(e, "timed out")); } EXPECT_TRUE(exp); - EXPECT_TRUE(hasProcessExited(p.pid)); + //p is invalid when spawn goes wrong, cannot be checked against } TEST(Spawn, Normal) { - hobbes::proc p; + hobbes::proc p{}; unsetenv(KEY); startChild(2, p); // should not throw any exceptions }