This is an archive of the discontinued LLVM Phabricator instance.

[flang] Debugging of ACCESS='STREAM' I/O
ClosedPublic

Authored by klausler on Feb 2 2022, 11:18 AM.

Details

Summary

Corrects the runtime implementation of I/O on files with
the access mode ACCESS='STREAM'. This is a collection
of edge-case tweaks to ensure that the distinctions between
stream and direct/sequential files, unformatted or formatted,
are respected where appropriate.
Moves NextInField() from io-stmt.h to io-stmt.cpp --
it was getting too big to keep in a header.

Diff Detail

Event Timeline

klausler created this revision.Feb 2 2022, 11:18 AM
klausler requested review of this revision.Feb 2 2022, 11:18 AM
vdonaldson accepted this revision.Feb 2 2022, 11:41 AM
This revision is now accepted and ready to land.Feb 2 2022, 11:41 AM
This revision was landed with ongoing or failed builds.Feb 2 2022, 1:09 PM
This revision was automatically updated to reflect the committed changes.
Herald added a project: Restricted Project. · View Herald TranscriptFeb 2 2022, 1:09 PM

This patch causes the test flang-Unit::ExternalIOTests.TestWriteAfterNonAvancingInput to fail under Windows (https://lab.llvm.org/buildbot/#/builders/172/builds/7664)

[ RUN      ] ExternalIOTests.TestWriteAfterNonAvancingInput
C:\Users\buildbot-worker\minipc-ryzen-win\flang-x86_64-windows\llvm-project\flang\unittests\Runtime\ExternalIOTest.cpp(649): error: Expected equality of these values:
  resultRecord
    Which is: "ABCDEFGHXYZ\r        "
  expectedRecord
    Which is: "ABCDEFGHXYZ         "
Record after non advancing read followed by wrote

@klausler Thanks for this patch! I was hoping that I could find a fix for the failure on Windows myself, but no luck. I reverted instead - our Windows buildbot is one of our fastest and reliable CI machines. Also, while this does not work on Windows, our pre-commit CI is unnecessarily noisy.

Please, could take a look and re-submit?

@klausler Thanks for this patch! I was hoping that I could find a fix for the failure on Windows myself, but no luck. I reverted instead - our Windows buildbot is one of our fastest and reliable CI machines. Also, while this does not work on Windows, our pre-commit CI is unnecessarily noisy.

Please, could take a look and re-submit?

It seems that this patch exposed a problem; I suspect file truncation on Windows. I may resubmit later.

Thanks for reverting. The stray \r makes me suspect something removed an \n but left over the second byte from Windows CRLF line endings.

If needed, I can look for the problem on Windows.

Thanks for reverting. The stray \r makes me suspect something removed an \n but left over the second byte from Windows CRLF line endings.

If needed, I can look for the problem on Windows.

The f18 runtime doesn't emit \r (yet). So I don't know from whence it came, if it did indeed come from the f18 runtime.

The runtime uses a temporary file in scratch mode that the unittest uses, which is opened in text mode. Under Windows, when writing \n to a file opened in text mode, it will actually write \r\n. However, the internal position counter frameOffsetInFile_ will not take the additional character into account. On Rewind, it will truncate the file to the frameOffsetInFile_ size, keeping the first \r but truncating the second character \n away.

This makes the test pass:

diff --git a/flang/runtime/file.cpp b/flang/runtime/file.cpp
index 4e36978cfb23..787845f78353 100644
--- a/flang/runtime/file.cpp
+++ b/flang/runtime/file.cpp
@@ -46,7 +46,7 @@ static int openfile_mkstemp(IoErrorHandler &handler) {
     return -1;
   }
   int fd{::_open(
-      tempFileName, _O_CREAT | _O_TEMPORARY | _O_RDWR, _S_IREAD | _S_IWRITE)};
+      tempFileName, _O_CREAT | _O_BINARY | _O_TEMPORARY | _O_RDWR, _S_IREAD | _S_IWRITE)};
 #else
   char path[]{"/tmp/Fortran-Scratch-XXXXXX"};
   int fd{::mkstemp(path)};

However, I don't think this is an universal solution, as stdout and stderr are always in text mode.

The runtime uses a temporary file in scratch mode that the unittest uses, which is opened in text mode. Under Windows, when writing \n to a file opened in text mode, it will actually write \r\n. However, the internal position counter frameOffsetInFile_ will not take the additional character into account. On Rewind, it will truncate the file to the frameOffsetInFile_ size, keeping the first \r but truncating the second character \n away.

This makes the test pass:

diff --git a/flang/runtime/file.cpp b/flang/runtime/file.cpp
index 4e36978cfb23..787845f78353 100644
--- a/flang/runtime/file.cpp
+++ b/flang/runtime/file.cpp
@@ -46,7 +46,7 @@ static int openfile_mkstemp(IoErrorHandler &handler) {
     return -1;
   }
   int fd{::_open(
-      tempFileName, _O_CREAT | _O_TEMPORARY | _O_RDWR, _S_IREAD | _S_IWRITE)};
+      tempFileName, _O_CREAT | _O_BINARY | _O_TEMPORARY | _O_RDWR, _S_IREAD | _S_IWRITE)};
 #else
   char path[]{"/tmp/Fortran-Scratch-XXXXXX"};
   int fd{::mkstemp(path)};

However, I don't think this is an universal solution, as stdout and stderr are always in text mode.

Thanks, that's a helpful clue. Unfortunately in Fortran we can't always know whether a file will be formatted or unformatted at the time that the file is opened, so the runtime will probably have to always use binary mode and emit explicit carriage returns. Stdout and stderr being in text mode is not much of a problem -- they don't have to be positionable and are always formatted. I will get back to this in a few weeks after I dig out from under a pile of more important things.