Skip to content

[flang][runtime] Better handling of "fort.N" opening errors #96347

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jun 24, 2024

Conversation

klausler
Copy link
Contributor

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.

@klausler klausler requested a review from vdonaldson June 21, 2024 18:39
@llvmbot llvmbot added flang:runtime flang Flang issues not falling into any other category labels Jun 21, 2024
@llvmbot
Copy link
Member

llvmbot commented Jun 21, 2024

@llvm/pr-subscribers-flang-runtime

Author: Peter Klausler (klausler)

Changes

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.


Full diff: https://github.com/llvm/llvm-project/pull/96347.diff

2 Files Affected:

  • (modified) flang/runtime/external-unit.cpp (+13-5)
  • (modified) flang/runtime/unit.h (+1-1)
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();

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.
@klausler klausler merged commit eac925f into llvm:main Jun 24, 2024
7 checks passed
@klausler klausler deleted the bug1473 branch June 24, 2024 17:34
AlexisPerry pushed a commit to llvm-project-tlp/llvm-project that referenced this pull request Jul 9, 2024
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.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
flang:runtime flang Flang issues not falling into any other category
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants