[flang-commits] [flang] c84616c - [flang] Avoid potential deadlock in CloseAll()

Peter Klausler via flang-commits flang-commits at lists.llvm.org
Tue Dec 7 09:43:01 PST 2021


Author: Peter Klausler
Date: 2021-12-07T09:42:48-08:00
New Revision: c84616c3b368f1ca679a08d2ce131f01a9f14ce9

URL: https://github.com/llvm/llvm-project/commit/c84616c3b368f1ca679a08d2ce131f01a9f14ce9
DIFF: https://github.com/llvm/llvm-project/commit/c84616c3b368f1ca679a08d2ce131f01a9f14ce9.diff

LOG: [flang] Avoid potential deadlock in CloseAll()

When closing all open units, don't hold the unit map lock
over the actual close operations; if one of those aborts,
CloseAll() may be called and then deadlock.

Differential Review: https://reviews.llvm.org/D115184

Added: 
    

Modified: 
    flang/runtime/unit-map.cpp

Removed: 
    


################################################################################
diff  --git a/flang/runtime/unit-map.cpp b/flang/runtime/unit-map.cpp
index 497cef23d47c3..4c931871c0176 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<Chain> 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) {


        


More information about the flang-commits mailing list