Skip to content

Commit dd05f14

Browse files
committed
einsum: fence sub-Worlds before destruction (incl. on exception unwind)
Add an inline RAII guard `FenceSubWorldsOnExit` to the generalized- contraction path of einsum, declared right after the `worlds` vector so it destructs *before* `worlds` (LIFO) and *after* AB/C. On normal exit this is a second harmless fence; on exception unwind it drains any `lazy_sync_children` tasks that ~DistArray scheduled via lazy_deleter on sub-World taskqs before those sub-Worlds are torn down. Without this, those tasks survive into the global ThreadPool past ~World, then trip ~WorldObject's `World::exists(&world)` assertion when an enclosing scope's fence runs them, masking the real exception with a cryptic abort.
1 parent f9f3828 commit dd05f14

1 file changed

Lines changed: 23 additions & 0 deletions

File tree

src/TiledArray/einsum/tiledarray.h

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -653,6 +653,29 @@ auto einsum(expressions::TsrExpr<ArrayA_> A, expressions::TsrExpr<ArrayB_> B,
653653
// dead World (e.g. while unwinding an exception thrown mid-contraction).
654654
std::vector<std::shared_ptr<World>> worlds;
655655

656+
// RAII fencer: on normal exit and (critically) on exception unwind,
657+
// fence every live sub-World before it is destroyed. ~DistArray ->
658+
// lazy_deleter calls world.gop.lazy_sync(...) which enqueues a
659+
// lazy_sync_children task onto the sub-World's taskq; without a fence
660+
// those tasks survive into the global ThreadPool past the sub-World's
661+
// ~World, then trip ~WorldObject's `World::exists(&world)` assertion
662+
// when some later fence (e.g. an enclosing scope's fence run during
663+
// unwind) picks them up. Declared *after* `worlds` so it destructs
664+
// *before* `worlds` (LIFO); destructs *after* AB/C so it sees the
665+
// tasks they scheduled via lazy_deleter.
666+
struct FenceSubWorldsOnExit {
667+
std::vector<std::shared_ptr<World>> &worlds_;
668+
~FenceSubWorldsOnExit() {
669+
for (auto &w : worlds_) {
670+
if (!w) continue;
671+
try {
672+
w->gop.fence();
673+
} catch (...) {
674+
}
675+
}
676+
}
677+
} fence_subworlds_on_exit{worlds};
678+
656679
std::tuple<ArrayTerm<ArrayA>, ArrayTerm<ArrayB>> AB{{A.array(), a},
657680
{B.array(), b}};
658681

0 commit comments

Comments
 (0)