[flang-commits] [flang] 341c7c0 - [flang][runtime] Improve Fortran I/O behavior when main program is C/C++

Peter Klausler via flang-commits flang-commits at lists.llvm.org
Thu Aug 18 14:11:02 PDT 2022


Author: Peter Klausler
Date: 2022-08-18T14:10:45-07:00
New Revision: 341c7c05df87394ac23842a0c27889b11a625058

URL: https://github.com/llvm/llvm-project/commit/341c7c05df87394ac23842a0c27889b11a625058
DIFF: https://github.com/llvm/llvm-project/commit/341c7c05df87394ac23842a0c27889b11a625058.diff

LOG: [flang][runtime] Improve Fortran I/O behavior when main program is C/C++

Ensure that I/O buffers are flushed at the end of the program,
and properly detect ttys for predefined units so that Fortran
output is interspersed with output from non-Fortran code.

Fixes https://github.com/llvm/llvm-project/issues/56944

Differential Revision: https://reviews.llvm.org/D132152

Update: fix typo in comment

Added: 
    

Modified: 
    flang/runtime/file.cpp
    flang/runtime/unit.cpp
    flang/runtime/unit.h

Removed: 
    


################################################################################
diff  --git a/flang/runtime/file.cpp b/flang/runtime/file.cpp
index 8ff9724762858..b2af0fd7aac3c 100644
--- a/flang/runtime/file.cpp
+++ b/flang/runtime/file.cpp
@@ -134,7 +134,7 @@ void OpenFile::Open(OpenStatus status, std::optional<Action> action,
   if (position == Position::Append && !RawSeekToEnd()) {
     handler.SignalError(IostatOpenBadAppend);
   }
-  isTerminal_ = ::isatty(fd_) == 1;
+  isTerminal_ = IsATerminal(fd_) == 1;
   mayRead_ = *action != Action::Write;
   mayWrite_ = *action != Action::Read;
   if (status == OpenStatus::Old || status == OpenStatus::Unknown) {
@@ -163,6 +163,7 @@ void OpenFile::Predefine(int fd) {
   knownSize_.reset();
   nextId_ = 0;
   pending_.reset();
+  isTerminal_ = IsATerminal(fd_) == 1;
   mayRead_ = fd == 0;
   mayWrite_ = fd != 0;
   mayPosition_ = false;

diff  --git a/flang/runtime/unit.cpp b/flang/runtime/unit.cpp
index ac6311f0408f4..ff7b8938e833d 100644
--- a/flang/runtime/unit.cpp
+++ b/flang/runtime/unit.cpp
@@ -206,42 +206,58 @@ Iostat ExternalFileUnit::SetDirection(Direction direction) {
   }
 }
 
-UnitMap &ExternalFileUnit::GetUnitMap() {
-  if (unitMap) {
-    return *unitMap;
-  }
-  CriticalSection critical{unitMapLock};
-  if (unitMap) {
-    return *unitMap;
-  }
+UnitMap &ExternalFileUnit::CreateUnitMap() {
   Terminator terminator{__FILE__, __LINE__};
   IoErrorHandler handler{terminator};
-  UnitMap *newUnitMap{New<UnitMap>{terminator}().release()};
+  UnitMap &newUnitMap{*New<UnitMap>{terminator}().release()};
 
   bool wasExtant{false};
-  ExternalFileUnit &out{*newUnitMap->LookUpOrCreate(6, terminator, wasExtant)};
+  ExternalFileUnit &out{*newUnitMap.LookUpOrCreate(6, terminator, wasExtant)};
   RUNTIME_CHECK(terminator, !wasExtant);
   out.Predefine(1);
   handler.SignalError(out.SetDirection(Direction::Output));
   out.isUnformatted = false;
   defaultOutput = &out;
 
-  ExternalFileUnit &in{*newUnitMap->LookUpOrCreate(5, terminator, wasExtant)};
+  ExternalFileUnit &in{*newUnitMap.LookUpOrCreate(5, terminator, wasExtant)};
   RUNTIME_CHECK(terminator, !wasExtant);
   in.Predefine(0);
   handler.SignalError(in.SetDirection(Direction::Input));
   in.isUnformatted = false;
   defaultInput = ∈
 
-  ExternalFileUnit &error{
-      *newUnitMap->LookUpOrCreate(0, terminator, wasExtant)};
+  ExternalFileUnit &error{*newUnitMap.LookUpOrCreate(0, terminator, wasExtant)};
   RUNTIME_CHECK(terminator, !wasExtant);
   error.Predefine(2);
   handler.SignalError(error.SetDirection(Direction::Output));
   error.isUnformatted = false;
   errorOutput = &error;
 
-  unitMap = newUnitMap;
+  return newUnitMap;
+}
+
+// A back-up atexit() handler for programs that don't terminate with a main
+// program END or a STOP statement or other Fortran-initiated program shutdown,
+// such as programs with a C main() that terminate normally.  It flushes all
+// external I/O units.  It is registered once the first time that any external
+// I/O is attempted.
+static void CloseAllExternalUnits() {
+  IoErrorHandler handler{"Fortran program termination"};
+  ExternalFileUnit::CloseAll(handler);
+}
+
+UnitMap &ExternalFileUnit::GetUnitMap() {
+  if (unitMap) {
+    return *unitMap;
+  }
+  {
+    CriticalSection critical{unitMapLock};
+    if (unitMap) {
+      return *unitMap;
+    }
+    unitMap = &CreateUnitMap();
+  }
+  std::atexit(CloseAllExternalUnits);
   return *unitMap;
 }
 

diff  --git a/flang/runtime/unit.h b/flang/runtime/unit.h
index a456a49378947..535f3ba3f6031 100644
--- a/flang/runtime/unit.h
+++ b/flang/runtime/unit.h
@@ -119,6 +119,7 @@ class ExternalFileUnit : public ConnectionState,
   bool Wait(int);
 
 private:
+  static UnitMap &CreateUnitMap();
   static UnitMap &GetUnitMap();
   const char *FrameNextInput(IoErrorHandler &, std::size_t);
   void SetPosition(std::int64_t, IoErrorHandler &); // zero-based


        


More information about the flang-commits mailing list