Skip to content

Commit c466750

Browse files
klauslerAlexisPerry
authored andcommitted
[flang][runtime] Better handling of "fort.N" opening errors (llvm#96347)
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.
1 parent 3b0d937 commit c466750

File tree

3 files changed

+15
-7
lines changed

3 files changed

+15
-7
lines changed

flang/runtime/external-unit.cpp

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -65,10 +65,17 @@ ExternalFileUnit *ExternalFileUnit::LookUpOrCreateAnonymous(int unit,
6565
bool exists{false};
6666
ExternalFileUnit *result{GetUnitMap().LookUpOrCreate(unit, handler, exists)};
6767
if (result && !exists) {
68-
result->OpenAnonymousUnit(
69-
dir == Direction::Input ? OpenStatus::Unknown : OpenStatus::Replace,
70-
Action::ReadWrite, Position::Rewind, Convert::Unknown, handler);
71-
result->isUnformatted = isUnformatted;
68+
if (!result->OpenAnonymousUnit(
69+
dir == Direction::Input ? OpenStatus::Unknown : OpenStatus::Replace,
70+
Action::ReadWrite, Position::Rewind, Convert::Unknown, handler)) {
71+
// fort.N isn't a writable file
72+
if (ExternalFileUnit * closed{LookUpForClose(result->unitNumber())}) {
73+
closed->DestroyClosed();
74+
}
75+
result = nullptr;
76+
} else {
77+
result->isUnformatted = isUnformatted;
78+
}
7279
}
7380
return result;
7481
}
@@ -183,7 +190,7 @@ bool ExternalFileUnit::OpenUnit(Fortran::common::optional<OpenStatus> status,
183190
return impliedClose;
184191
}
185192

186-
void ExternalFileUnit::OpenAnonymousUnit(
193+
bool ExternalFileUnit::OpenAnonymousUnit(
187194
Fortran::common::optional<OpenStatus> status,
188195
Fortran::common::optional<Action> action, Position position,
189196
Convert convert, IoErrorHandler &handler) {
@@ -193,6 +200,7 @@ void ExternalFileUnit::OpenAnonymousUnit(
193200
std::snprintf(path.get(), pathMaxLen, "fort.%d", unitNumber_);
194201
OpenUnit(status, action, position, std::move(path), std::strlen(path.get()),
195202
convert, handler);
203+
return IsConnected();
196204
}
197205

198206
void ExternalFileUnit::CloseUnit(CloseStatus status, IoErrorHandler &handler) {

flang/runtime/pseudo-unit.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ bool ExternalFileUnit::OpenUnit(Fortran::common::optional<OpenStatus> status,
6565
handler.Crash("%s: unsupported", RT_PRETTY_FUNCTION);
6666
}
6767

68-
void ExternalFileUnit::OpenAnonymousUnit(Fortran::common::optional<OpenStatus>,
68+
bool ExternalFileUnit::OpenAnonymousUnit(Fortran::common::optional<OpenStatus>,
6969
Fortran::common::optional<Action>, Position, Convert convert,
7070
IoErrorHandler &handler) {
7171
handler.Crash("%s: unsupported", RT_PRETTY_FUNCTION);

flang/runtime/unit.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ class ExternalFileUnit : public ConnectionState,
134134
RT_API_ATTRS bool OpenUnit(Fortran::common::optional<OpenStatus>,
135135
Fortran::common::optional<Action>, Position, OwningPtr<char> &&path,
136136
std::size_t pathLength, Convert, IoErrorHandler &);
137-
RT_API_ATTRS void OpenAnonymousUnit(Fortran::common::optional<OpenStatus>,
137+
RT_API_ATTRS bool OpenAnonymousUnit(Fortran::common::optional<OpenStatus>,
138138
Fortran::common::optional<Action>, Position, Convert, IoErrorHandler &);
139139
RT_API_ATTRS void CloseUnit(CloseStatus, IoErrorHandler &);
140140
RT_API_ATTRS void DestroyClosed();

0 commit comments

Comments
 (0)