[flang-commits] [flang] [flang][runtime] Better handling of "fort.N" opening errors (PR #96347)
Peter Klausler via flang-commits
flang-commits at lists.llvm.org
Fri Jun 21 11:39:09 PDT 2024
https://github.com/klausler created https://github.com/llvm/llvm-project/pull/96347
When a data transfer statement references a unit number that hasn't been explicitly OPENed, the runtime I/O support library opens a local "fort.N" file where N is the unit number. If that name exists in the current working directory but is not a readable or writable file (as appropriate), the runtime needs to catch the error at the point of the READ or WRITE statement rather than leaving an open unit in the unit map without a valid file descriptor.
>From 87142af496f6ed7c6f93069047c27a88c8e037de Mon Sep 17 00:00:00 2001
From: Peter Klausler <pklausler at nvidia.com>
Date: Fri, 21 Jun 2024 11:28:27 -0700
Subject: [PATCH] [flang][runtime] Better handling of "fort.N" opening errors
When a data transfer statement references a unit number that hasn't been
explicitly OPENed, the runtime I/O support library opens a local
"fort.N" file where N is the unit number. If that name exists in
the current working directory but is not a readable or writable
file (as appropriate), the runtime needs to catch the error at the
point of the READ or WRITE statement rather than leaving an open
unit in the unit map without a valid file descriptor.
---
flang/runtime/external-unit.cpp | 18 +++++++++++++-----
flang/runtime/unit.h | 2 +-
2 files changed, 14 insertions(+), 6 deletions(-)
diff --git a/flang/runtime/external-unit.cpp b/flang/runtime/external-unit.cpp
index 328c994a180b1..8009151a8a370 100644
--- a/flang/runtime/external-unit.cpp
+++ b/flang/runtime/external-unit.cpp
@@ -65,10 +65,17 @@ ExternalFileUnit *ExternalFileUnit::LookUpOrCreateAnonymous(int unit,
bool exists{false};
ExternalFileUnit *result{GetUnitMap().LookUpOrCreate(unit, handler, exists)};
if (result && !exists) {
- result->OpenAnonymousUnit(
- dir == Direction::Input ? OpenStatus::Unknown : OpenStatus::Replace,
- Action::ReadWrite, Position::Rewind, Convert::Unknown, handler);
- result->isUnformatted = isUnformatted;
+ if (!result->OpenAnonymousUnit(
+ dir == Direction::Input ? OpenStatus::Unknown : OpenStatus::Replace,
+ Action::ReadWrite, Position::Rewind, Convert::Unknown, handler)) {
+ // fort.N isn't a writable file
+ if (ExternalFileUnit * closed{LookUpForClose(result->unitNumber())}) {
+ closed->DestroyClosed();
+ }
+ result = nullptr;
+ } else {
+ result->isUnformatted = isUnformatted;
+ }
}
return result;
}
@@ -183,7 +190,7 @@ bool ExternalFileUnit::OpenUnit(Fortran::common::optional<OpenStatus> status,
return impliedClose;
}
-void ExternalFileUnit::OpenAnonymousUnit(
+bool ExternalFileUnit::OpenAnonymousUnit(
Fortran::common::optional<OpenStatus> status,
Fortran::common::optional<Action> action, Position position,
Convert convert, IoErrorHandler &handler) {
@@ -193,6 +200,7 @@ void ExternalFileUnit::OpenAnonymousUnit(
std::snprintf(path.get(), pathMaxLen, "fort.%d", unitNumber_);
OpenUnit(status, action, position, std::move(path), std::strlen(path.get()),
convert, handler);
+ return IsConnected();
}
void ExternalFileUnit::CloseUnit(CloseStatus status, IoErrorHandler &handler) {
diff --git a/flang/runtime/unit.h b/flang/runtime/unit.h
index abd535fd0381d..83f839e205a48 100644
--- a/flang/runtime/unit.h
+++ b/flang/runtime/unit.h
@@ -134,7 +134,7 @@ class ExternalFileUnit : public ConnectionState,
RT_API_ATTRS bool OpenUnit(Fortran::common::optional<OpenStatus>,
Fortran::common::optional<Action>, Position, OwningPtr<char> &&path,
std::size_t pathLength, Convert, IoErrorHandler &);
- RT_API_ATTRS void OpenAnonymousUnit(Fortran::common::optional<OpenStatus>,
+ RT_API_ATTRS bool OpenAnonymousUnit(Fortran::common::optional<OpenStatus>,
Fortran::common::optional<Action>, Position, Convert, IoErrorHandler &);
RT_API_ATTRS void CloseUnit(CloseStatus, IoErrorHandler &);
RT_API_ATTRS void DestroyClosed();
More information about the flang-commits
mailing list