[flang-commits] [flang] a8f2d18 - [flang][runtime] Resilient opening of anonymous unit (#93876)
via flang-commits
flang-commits at lists.llvm.org
Mon Jun 3 14:23:54 PDT 2024
Author: Peter Klausler
Date: 2024-06-03T14:23:50-07:00
New Revision: a8f2d185b252e9a4b5676d29194d78eaf14ed219
URL: https://github.com/llvm/llvm-project/commit/a8f2d185b252e9a4b5676d29194d78eaf14ed219
DIFF: https://github.com/llvm/llvm-project/commit/a8f2d185b252e9a4b5676d29194d78eaf14ed219.diff
LOG: [flang][runtime] Resilient opening of anonymous unit (#93876)
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.
Added:
Modified:
flang/runtime/external-unit.cpp
flang/runtime/file.cpp
flang/runtime/io-api-common.h
flang/runtime/pseudo-unit.cpp
flang/runtime/unit.h
Removed:
################################################################################
diff --git a/flang/runtime/external-unit.cpp b/flang/runtime/external-unit.cpp
index 4bfa218bb7769..328c994a180b1 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) {
- // Make sure that the returned anonymous unit has been opened
+ 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..ec772903242b8 100644
--- a/flang/runtime/file.cpp
+++ b/flang/runtime/file.cpp
@@ -131,17 +131,17 @@ void OpenFile::Open(OpenStatus status, Fortran::common::optional<Action> action,
}
RUNTIME_CHECK(handler, action.has_value());
pending_.reset();
- if (position == Position::Append && !RawSeekToEnd()) {
+ if (fd_ >= 0 && position == Position::Append && !RawSeekToEnd()) {
handler.SignalError(IostatOpenBadAppend);
}
- isTerminal_ = IsATerminal(fd_) == 1;
+ isTerminal_ = fd_ >= 0 && IsATerminal(fd_) == 1;
mayRead_ = *action != Action::Write;
mayWrite_ = *action != Action::Read;
if (status == OpenStatus::Old || status == OpenStatus::Unknown) {
knownSize_.reset();
#ifndef _WIN32
struct stat buf;
- if (::fstat(fd_, &buf) == 0) {
+ if (fd_ >= 0 && ::fstat(fd_, &buf) == 0) {
mayPosition_ = S_ISREG(buf.st_mode);
knownSize_ = buf.st_size;
}
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 &);
More information about the flang-commits
mailing list