forked from OSchip/llvm-project
[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
This commit is contained in:
parent
622d689480
commit
c84616c3b3
|
@ -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) {
|
||||
|
|
Loading…
Reference in New Issue