diff --git a/flang/runtime/unit-map.cpp b/flang/runtime/unit-map.cpp index 497cef23d47c..4c931871c017 100644 --- a/flang/runtime/unit-map.cpp +++ b/flang/runtime/unit-map.cpp @@ -52,15 +52,24 @@ void UnitMap::DestroyClosed(ExternalFileUnit &unit) { } void UnitMap::CloseAll(IoErrorHandler &handler) { - CriticalSection critical{lock_}; - for (int j{0}; j < buckets_; ++j) { - while (Chain * p{bucket_[j].get()}) { - bucket_[j].swap(p->next); // pops p from head of list - p->unit.CloseUnit(CloseStatus::Keep, handler); - p->unit.~ExternalFileUnit(); - FreeMemory(p); + // Extract units from the map so they can be closed + // without holding lock_. + OwningPtr closeList; + { + CriticalSection critical{lock_}; + for (int j{0}; j < buckets_; ++j) { + while (Chain * p{bucket_[j].get()}) { + bucket_[j].swap(p->next); // pops p from head of bucket list + closeList.swap(p->next); // pushes p to closeList + } } } + while (Chain * p{closeList.get()}) { + closeList.swap(p->next); // pops p from head of closeList + p->unit.CloseUnit(CloseStatus::Keep, handler); + p->unit.~ExternalFileUnit(); + FreeMemory(p); + } } void UnitMap::FlushAll(IoErrorHandler &handler) {