Skip to content

Commit ae9d873

Browse files
committed
Frontend: add an option -bad-file-descriptor-retry-count
This option allows the compiler to retry opening an input file if the previous opening returns an error of bad file descriptor. Swift-driver will set this argument in certain circumstances to walk-around such error. rdar://73157185
1 parent 461b524 commit ae9d873

File tree

9 files changed

+80
-11
lines changed

9 files changed

+80
-11
lines changed

include/swift/Basic/FileSystem.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,8 @@ namespace swift {
8080
llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>
8181
getFileOrSTDIN(llvm::vfs::FileSystem &FS,
8282
const llvm::Twine &Name, int64_t FileSize = -1,
83-
bool RequiresNullTerminator = true, bool IsVolatile = false);
83+
bool RequiresNullTerminator = true, bool IsVolatile = false,
84+
unsigned BADFRetry = 0);
8485
} // end namespace vfs
8586

8687
} // end namespace swift

include/swift/Frontend/FrontendOptions.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,9 @@ class FrontendOptions {
8686
/// The module for which we should verify all of the generic signatures.
8787
std::string VerifyGenericSignaturesInModule;
8888

89+
/// Number of retry opening an input file if the previous opening returns
90+
/// bad file descriptor error.
91+
unsigned BadFileDescriptorRetryCount = 0;
8992
enum class ActionType {
9093
NoneAction, ///< No specific action
9194
Parse, ///< Parse only

include/swift/Option/FrontendOptions.td

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -786,4 +786,8 @@ def experimental_allow_module_with_compiler_errors:
786786
Flags<[HelpHidden]>,
787787
HelpText<"Attempt to output .swiftmodule, regardless of compilation errors">;
788788

789+
def bad_file_descriptor_retry_count:
790+
Separate<["-"], "bad-file-descriptor-retry-count">,
791+
HelpText<"Number of retrying opening a file if previous open returns a bad "
792+
"file descriptor error.">;
789793
} // end let Flags = [FrontendOption, NoDriverOption, HelpHidden]

lib/Basic/FileSystem.cpp

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -273,12 +273,21 @@ swift::vfs::getFileOrSTDIN(llvm::vfs::FileSystem &FS,
273273
const llvm::Twine &Filename,
274274
int64_t FileSize,
275275
bool RequiresNullTerminator,
276-
bool IsVolatile) {
276+
bool IsVolatile,
277+
unsigned BADFRetry) {
277278
llvm::SmallString<256> NameBuf;
278279
llvm::StringRef NameRef = Filename.toStringRef(NameBuf);
279280

280281
if (NameRef == "-")
281282
return llvm::MemoryBuffer::getSTDIN();
282-
return FS.getBufferForFile(Filename, FileSize,
283-
RequiresNullTerminator, IsVolatile);
283+
llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> inputFileOrErr = nullptr;
284+
for (unsigned I = 0; I != BADFRetry + 1; ++ I) {
285+
inputFileOrErr = FS.getBufferForFile(Filename, FileSize,
286+
RequiresNullTerminator, IsVolatile);
287+
if (inputFileOrErr)
288+
return inputFileOrErr;
289+
if (inputFileOrErr.getError().value() != EBADF)
290+
return inputFileOrErr;
291+
}
292+
return inputFileOrErr;
284293
}

lib/Frontend/ArgsToFrontendInputsConverter.cpp

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,9 @@ ArgsToFrontendInputsConverter::ArgsToFrontendInputsConverter(
3434
DiagnosticEngine &diags, const ArgList &args)
3535
: Diags(diags), Args(args),
3636
FilelistPathArg(args.getLastArg(options::OPT_filelist)),
37-
PrimaryFilelistPathArg(args.getLastArg(options::OPT_primary_filelist)) {}
37+
PrimaryFilelistPathArg(args.getLastArg(options::OPT_primary_filelist)),
38+
BadFileDescriptorRetryCountArg(
39+
args.getLastArg(options::OPT_bad_file_descriptor_retry_count)) {}
3840

3941
Optional<FrontendInputsAndOutputs> ArgsToFrontendInputsConverter::convert(
4042
SmallVectorImpl<std::unique_ptr<llvm::MemoryBuffer>> *buffers) {
@@ -118,8 +120,26 @@ bool ArgsToFrontendInputsConverter::forAllFilesInFilelist(
118120
if (!pathArg)
119121
return false;
120122
StringRef path = pathArg->getValue();
121-
llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> filelistBufferOrError =
122-
llvm::MemoryBuffer::getFile(path);
123+
124+
// Honor -bad-file-descriptor-retry-count from the argument list
125+
unsigned RetryCount = 0;
126+
if (BadFileDescriptorRetryCountArg &&
127+
StringRef(BadFileDescriptorRetryCountArg->getValue())
128+
.getAsInteger(10,RetryCount)) {
129+
Diags.diagnose(SourceLoc(), diag::error_invalid_arg_value,
130+
BadFileDescriptorRetryCountArg->getAsString(Args),
131+
BadFileDescriptorRetryCountArg->getValue());
132+
return true;
133+
}
134+
135+
llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> filelistBufferOrError = nullptr;
136+
for (unsigned I = 0; I < RetryCount + 1; ++I) {
137+
filelistBufferOrError = llvm::MemoryBuffer::getFile(path);
138+
if (filelistBufferOrError)
139+
break;
140+
if (filelistBufferOrError.getError().value() != EBADF)
141+
break;
142+
}
123143
if (!filelistBufferOrError) {
124144
Diags.diagnose(SourceLoc(), diag::cannot_open_file, path,
125145
filelistBufferOrError.getError().message());

lib/Frontend/ArgsToFrontendInputsConverter.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ class ArgsToFrontendInputsConverter {
4747

4848
llvm::opt::Arg const *const FilelistPathArg;
4949
llvm::opt::Arg const *const PrimaryFilelistPathArg;
50+
llvm::opt::Arg const *const BadFileDescriptorRetryCountArg;
5051

5152
/// A place to keep alive any buffers that are loaded as part of setting up
5253
/// the frontend inputs.

lib/Frontend/ArgsToFrontendOptionsConverter.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,16 @@ bool ArgsToFrontendOptionsConverter::convert(
8989
IntermoduleDepTrackingMode::IncludeSystem;
9090
}
9191

92+
if (const Arg *A = Args.getLastArg(OPT_bad_file_descriptor_retry_count)) {
93+
unsigned limit;
94+
if (StringRef(A->getValue()).getAsInteger(10, limit)) {
95+
Diags.diagnose(SourceLoc(), diag::error_invalid_arg_value,
96+
A->getAsString(Args), A->getValue());
97+
return true;
98+
}
99+
Opts.BadFileDescriptorRetryCount = limit;
100+
}
101+
92102
Opts.DisableImplicitModules |= Args.hasArg(OPT_disable_implicit_swift_modules);
93103

94104
Opts.ImportPrescan |= Args.hasArg(OPT_import_prescan);

lib/Frontend/ArgsToFrontendOutputsConverter.cpp

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -588,8 +588,24 @@ SupplementaryOutputPathsComputer::readSupplementaryOutputFileMap() const {
588588
}
589589
const StringRef supplementaryFileMapPath =
590590
Args.getLastArgValue(options::OPT_supplementary_output_file_map);
591-
llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> buffer =
592-
llvm::MemoryBuffer::getFile(supplementaryFileMapPath);
591+
592+
unsigned BadFileDescriptorRetryCount = 0;
593+
if (const Arg *A = Args.getLastArg(options::OPT_bad_file_descriptor_retry_count)) {
594+
if (StringRef(A->getValue()).getAsInteger(10, BadFileDescriptorRetryCount)) {
595+
Diags.diagnose(SourceLoc(), diag::error_invalid_arg_value,
596+
A->getAsString(Args), A->getValue());
597+
return None;
598+
}
599+
}
600+
601+
llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> buffer = nullptr;
602+
for (unsigned I = 0; I < BadFileDescriptorRetryCount + 1; ++I) {
603+
buffer = llvm::MemoryBuffer::getFile(supplementaryFileMapPath);
604+
if (buffer)
605+
break;
606+
if (buffer.getError().value() != EBADF)
607+
break;
608+
}
593609
if (!buffer) {
594610
Diags.diagnose(SourceLoc(), diag::cannot_open_file,
595611
supplementaryFileMapPath, buffer.getError().message());

lib/Frontend/Frontend.cpp

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -668,8 +668,13 @@ Optional<ModuleBuffers> CompilerInstance::getInputBuffersIfPresent(
668668
// FIXME: Working with filenames is fragile, maybe use the real path
669669
// or have some kind of FileManager.
670670
using FileOrError = llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>;
671-
FileOrError inputFileOrErr = swift::vfs::getFileOrSTDIN(getFileSystem(),
672-
input.getFileName());
671+
FileOrError inputFileOrErr =
672+
swift::vfs::getFileOrSTDIN(getFileSystem(), input.getFileName(),
673+
/*FileSize*/-1,
674+
/*RequiresNullTerminator*/true,
675+
/*IsVolatile*/false,
676+
/*Bad File Descriptor Retry*/getInvocation().getFrontendOptions()
677+
.BadFileDescriptorRetryCount);
673678
if (!inputFileOrErr) {
674679
Diagnostics.diagnose(SourceLoc(), diag::error_open_input_file,
675680
input.getFileName(),

0 commit comments

Comments
 (0)