Skip to content

[flang][runtime] Resilient opening of anonymous unit #93876

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jun 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 6 additions & 5 deletions flang/runtime/external-unit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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) {
Expand Down
6 changes: 3 additions & 3 deletions flang/runtime/file.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down
8 changes: 6 additions & 2 deletions flang/runtime/io-api-common.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
}
Expand Down
4 changes: 2 additions & 2 deletions flang/runtime/pseudo-unit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
2 changes: 1 addition & 1 deletion flang/runtime/unit.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 &);
Expand Down
Loading