Skip to content

Commit 362364a

Browse files
committed
[flang][runtime] Resilient opening of anonymous unit
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.
1 parent 82bd7ad commit 362364a

File tree

5 files changed

+15
-9
lines changed

5 files changed

+15
-9
lines changed

flang/runtime/external-unit.cpp

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -58,15 +58,13 @@ ExternalFileUnit *ExternalFileUnit::LookUpOrCreate(
5858

5959
ExternalFileUnit *ExternalFileUnit::LookUpOrCreateAnonymous(int unit,
6060
Direction dir, Fortran::common::optional<bool> isUnformatted,
61-
const Terminator &terminator) {
61+
IoErrorHandler &handler) {
6262
// Make sure that the returned anonymous unit has been opened
6363
// not just created in the unitMap.
6464
CriticalSection critical{createOpenLock};
6565
bool exists{false};
66-
ExternalFileUnit *result{
67-
GetUnitMap().LookUpOrCreate(unit, terminator, exists)};
66+
ExternalFileUnit *result{GetUnitMap().LookUpOrCreate(unit, handler, exists)};
6867
if (result && !exists) {
69-
IoErrorHandler handler{terminator};
7068
result->OpenAnonymousUnit(
7169
dir == Direction::Input ? OpenStatus::Unknown : OpenStatus::Replace,
7270
Action::ReadWrite, Position::Rewind, Convert::Unknown, handler);
@@ -143,6 +141,9 @@ bool ExternalFileUnit::OpenUnit(Fortran::common::optional<OpenStatus> status,
143141
}
144142
set_path(std::move(newPath), newPathLength);
145143
Open(status.value_or(OpenStatus::Unknown), action, position, handler);
144+
if (handler.InError()) {
145+
return impliedClose;
146+
}
146147
auto totalBytes{knownSize()};
147148
if (access == Access::Direct) {
148149
if (!openRecl) {

flang/runtime/file.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,7 @@ void OpenFile::Open(OpenStatus status, Fortran::common::optional<Action> action,
126126
fd_ = ::open(path_.get(), flags, 0600);
127127
if (fd_ < 0) {
128128
handler.SignalErrno();
129+
return;
129130
}
130131
}
131132
}

flang/runtime/io-api-common.h

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,13 +33,17 @@ static inline RT_API_ATTRS Cookie NoopUnit(const Terminator &terminator,
3333
static inline RT_API_ATTRS ExternalFileUnit *GetOrCreateUnit(int unitNumber,
3434
Direction direction, Fortran::common::optional<bool> isUnformatted,
3535
const Terminator &terminator, Cookie &errorCookie) {
36+
IoErrorHandler handler{terminator};
37+
handler.HasIoStat();
3638
if (ExternalFileUnit *
3739
unit{ExternalFileUnit::LookUpOrCreateAnonymous(
38-
unitNumber, direction, isUnformatted, terminator)}) {
40+
unitNumber, direction, isUnformatted, handler)}) {
3941
errorCookie = nullptr;
4042
return unit;
4143
} else {
42-
errorCookie = NoopUnit(terminator, unitNumber, IostatBadUnitNumber);
44+
auto iostat{static_cast<enum Iostat>(handler.GetIoStat())};
45+
errorCookie = NoopUnit(terminator, unitNumber,
46+
iostat != IostatOk ? iostat : IostatBadUnitNumber);
4347
return nullptr;
4448
}
4549
}

flang/runtime/pseudo-unit.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,11 +36,11 @@ ExternalFileUnit *ExternalFileUnit::LookUpOrCreate(
3636

3737
ExternalFileUnit *ExternalFileUnit::LookUpOrCreateAnonymous(int unit,
3838
Direction direction, Fortran::common::optional<bool>,
39-
const Terminator &terminator) {
39+
IoErrorHandler &handler) {
4040
if (direction != Direction::Output) {
4141
terminator.Crash("ExternalFileUnit only supports output IO");
4242
}
43-
return New<ExternalFileUnit>{terminator}(unit).release();
43+
return New<ExternalFileUnit>{handler}(unit).release();
4444
}
4545

4646
ExternalFileUnit *ExternalFileUnit::LookUp(const char *, std::size_t) {

flang/runtime/unit.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ class ExternalFileUnit : public ConnectionState,
120120
int unit, const Terminator &, bool &wasExtant);
121121
static RT_API_ATTRS ExternalFileUnit *LookUpOrCreateAnonymous(int unit,
122122
Direction, Fortran::common::optional<bool> isUnformatted,
123-
const Terminator &);
123+
IoErrorHandler &);
124124
static RT_API_ATTRS ExternalFileUnit *LookUp(
125125
const char *path, std::size_t pathLen);
126126
static RT_API_ATTRS ExternalFileUnit &CreateNew(int unit, const Terminator &);

0 commit comments

Comments
 (0)