[flang-commits] [flang] [flang][runtime] Resilient opening of anonymous unit (PR #93876)
via flang-commits
flang-commits at lists.llvm.org
Thu May 30 13:33:33 PDT 2024
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-flang-runtime
Author: Peter Klausler (klausler)
<details>
<summary>Changes</summary>
When an I/O statement references a unit number that has not been explicitly opened or predefined, the I/O runtime support library opens a local "fort.N" file. If this fails, the program crashes, even when the I/O statement has IOSTAT= or IOMSG= or ERR= control list items. Connect the dots to enable resilience in these cases.
---
Full diff: https://github.com/llvm/llvm-project/pull/93876.diff
5 Files Affected:
- (modified) flang/runtime/external-unit.cpp (+5-4)
- (modified) flang/runtime/file.cpp (+1)
- (modified) flang/runtime/io-api-common.h (+6-2)
- (modified) flang/runtime/pseudo-unit.cpp (+2-2)
- (modified) flang/runtime/unit.h (+1-1)
``````````diff
diff --git a/flang/runtime/external-unit.cpp b/flang/runtime/external-unit.cpp
index 4bfa218bb7769..13926c2822205 100644
--- a/flang/runtime/external-unit.cpp
+++ b/flang/runtime/external-unit.cpp
@@ -58,15 +58,13 @@ ExternalFileUnit *ExternalFileUnit::LookUpOrCreate(
ExternalFileUnit *ExternalFileUnit::LookUpOrCreateAnonymous(int unit,
Direction dir, Fortran::common::optional<bool> isUnformatted,
- const Terminator &terminator) {
+ IoErrorHandler &handler) {
// Make sure that the returned anonymous unit has been opened
// not just created in the unitMap.
CriticalSection critical{createOpenLock};
bool exists{false};
- ExternalFileUnit *result{
- GetUnitMap().LookUpOrCreate(unit, terminator, exists)};
+ ExternalFileUnit *result{GetUnitMap().LookUpOrCreate(unit, handler, exists)};
if (result && !exists) {
- IoErrorHandler handler{terminator};
result->OpenAnonymousUnit(
dir == Direction::Input ? OpenStatus::Unknown : OpenStatus::Replace,
Action::ReadWrite, Position::Rewind, Convert::Unknown, handler);
@@ -143,6 +141,9 @@ bool ExternalFileUnit::OpenUnit(Fortran::common::optional<OpenStatus> status,
}
set_path(std::move(newPath), newPathLength);
Open(status.value_or(OpenStatus::Unknown), action, position, handler);
+ if (handler.InError()) {
+ return impliedClose;
+ }
auto totalBytes{knownSize()};
if (access == Access::Direct) {
if (!openRecl) {
diff --git a/flang/runtime/file.cpp b/flang/runtime/file.cpp
index 79db17e70acd9..67aa8d3cd13b0 100644
--- a/flang/runtime/file.cpp
+++ b/flang/runtime/file.cpp
@@ -126,6 +126,7 @@ void OpenFile::Open(OpenStatus status, Fortran::common::optional<Action> action,
fd_ = ::open(path_.get(), flags, 0600);
if (fd_ < 0) {
handler.SignalErrno();
+ return;
}
}
}
diff --git a/flang/runtime/io-api-common.h b/flang/runtime/io-api-common.h
index e9e050f6e7e61..c7b86cab73a52 100644
--- a/flang/runtime/io-api-common.h
+++ b/flang/runtime/io-api-common.h
@@ -33,13 +33,17 @@ static inline RT_API_ATTRS Cookie NoopUnit(const Terminator &terminator,
static inline RT_API_ATTRS ExternalFileUnit *GetOrCreateUnit(int unitNumber,
Direction direction, Fortran::common::optional<bool> isUnformatted,
const Terminator &terminator, Cookie &errorCookie) {
+ IoErrorHandler handler{terminator};
+ handler.HasIoStat();
if (ExternalFileUnit *
unit{ExternalFileUnit::LookUpOrCreateAnonymous(
- unitNumber, direction, isUnformatted, terminator)}) {
+ unitNumber, direction, isUnformatted, handler)}) {
errorCookie = nullptr;
return unit;
} else {
- errorCookie = NoopUnit(terminator, unitNumber, IostatBadUnitNumber);
+ auto iostat{static_cast<enum Iostat>(handler.GetIoStat())};
+ errorCookie = NoopUnit(terminator, unitNumber,
+ iostat != IostatOk ? iostat : IostatBadUnitNumber);
return nullptr;
}
}
diff --git a/flang/runtime/pseudo-unit.cpp b/flang/runtime/pseudo-unit.cpp
index a57e3a59efa5f..5a8696312d7ee 100644
--- a/flang/runtime/pseudo-unit.cpp
+++ b/flang/runtime/pseudo-unit.cpp
@@ -36,11 +36,11 @@ ExternalFileUnit *ExternalFileUnit::LookUpOrCreate(
ExternalFileUnit *ExternalFileUnit::LookUpOrCreateAnonymous(int unit,
Direction direction, Fortran::common::optional<bool>,
- const Terminator &terminator) {
+ IoErrorHandler &handler) {
if (direction != Direction::Output) {
terminator.Crash("ExternalFileUnit only supports output IO");
}
- return New<ExternalFileUnit>{terminator}(unit).release();
+ return New<ExternalFileUnit>{handler}(unit).release();
}
ExternalFileUnit *ExternalFileUnit::LookUp(const char *, std::size_t) {
diff --git a/flang/runtime/unit.h b/flang/runtime/unit.h
index e59fbbce2b577..abd535fd0381d 100644
--- a/flang/runtime/unit.h
+++ b/flang/runtime/unit.h
@@ -120,7 +120,7 @@ class ExternalFileUnit : public ConnectionState,
int unit, const Terminator &, bool &wasExtant);
static RT_API_ATTRS ExternalFileUnit *LookUpOrCreateAnonymous(int unit,
Direction, Fortran::common::optional<bool> isUnformatted,
- const Terminator &);
+ IoErrorHandler &);
static RT_API_ATTRS ExternalFileUnit *LookUp(
const char *path, std::size_t pathLen);
static RT_API_ATTRS ExternalFileUnit &CreateNew(int unit, const Terminator &);
``````````
</details>
https://github.com/llvm/llvm-project/pull/93876
More information about the flang-commits
mailing list