Skip to content

Commit c893e3d

Browse files
authored
[flang][runtime] Fix runtime crash after bad recoverable OPEN (llvm#111454)
When an OPEN statement with a unit number fails in a recoverable manner, the runtime needs to delete the ExternalFileUnit instance that was created in the unit map. And we do this too soon -- that instance still holds some of the I/O statement state that will be used by a later call into the runtime for EndIoStatement. Move the code that deletes the unit after a failed but recoverable OPEN into ExternalIoStatementBase::EndIoStatement, and don't do things afterwards that would need the I/O statement state that has been destroyed. Fixes llvm#111404.
1 parent 3f9998a commit c893e3d

File tree

2 files changed

+11
-5
lines changed

2 files changed

+11
-5
lines changed

flang/runtime/io-stmt.cpp

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -243,7 +243,15 @@ int ExternalIoStatementBase::EndIoStatement() {
243243
CompleteOperation();
244244
auto result{IoStatementBase::EndIoStatement()};
245245
#if !defined(RT_USE_PSEUDO_FILE_UNIT)
246+
auto unitNumber{unit_.unitNumber()};
246247
unit_.EndIoStatement(); // annihilates *this in unit_.u_
248+
if (destroy_) {
249+
if (ExternalFileUnit *
250+
toClose{ExternalFileUnit::LookUpForClose(unitNumber)}) {
251+
toClose->Close(CloseStatus::Delete, *this);
252+
toClose->DestroyClosed();
253+
}
254+
}
247255
#else
248256
// Fetch the unit pointer before *this disappears.
249257
ExternalFileUnit *unitPtr{&unit_};
@@ -329,11 +337,7 @@ void OpenStatementState::CompleteOperation() {
329337
}
330338
if (!wasExtant_ && InError()) {
331339
// Release the new unit on failure
332-
if (ExternalFileUnit *
333-
toClose{unit().LookUpForClose(unit().unitNumber())}) {
334-
toClose->Close(CloseStatus::Delete, *this);
335-
toClose->DestroyClosed();
336-
}
340+
set_destroy();
337341
}
338342
IoStatementBase::CompleteOperation();
339343
}

flang/runtime/io-stmt.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -455,6 +455,7 @@ class ExternalIoStatementBase : public IoStatementBase {
455455
RT_API_ATTRS MutableModes &mutableModes();
456456
RT_API_ATTRS ConnectionState &GetConnectionState();
457457
RT_API_ATTRS int asynchronousID() const { return asynchronousID_; }
458+
RT_API_ATTRS void set_destroy(bool yes = true) { destroy_ = yes; }
458459
RT_API_ATTRS int EndIoStatement();
459460
RT_API_ATTRS ExternalFileUnit *GetExternalFileUnit() const { return &unit_; }
460461
RT_API_ATTRS void SetAsynchronous();
@@ -463,6 +464,7 @@ class ExternalIoStatementBase : public IoStatementBase {
463464
private:
464465
ExternalFileUnit &unit_;
465466
int asynchronousID_{-1};
467+
bool destroy_{false};
466468
};
467469

468470
template <Direction DIR>

0 commit comments

Comments
 (0)