Skip to content

Commit fcbc2b4

Browse files
authored
Merge pull request swiftlang#35414 from nkcsgexi/volatile-open-input
Frontend: add an option -bad-file-descriptor-retry-count
2 parents 4f708fa + ae9d873 commit fcbc2b4

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
@@ -773,4 +773,8 @@ def experimental_allow_module_with_compiler_errors:
773773
Flags<[HelpHidden]>,
774774
HelpText<"Attempt to output .swiftmodule, regardless of compilation errors">;
775775

776+
def bad_file_descriptor_retry_count:
777+
Separate<["-"], "bad-file-descriptor-retry-count">,
778+
HelpText<"Number of retrying opening a file if previous open returns a bad "
779+
"file descriptor error.">;
776780
} // 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
@@ -567,8 +567,24 @@ SupplementaryOutputPathsComputer::readSupplementaryOutputFileMap() const {
567567
}
568568
const StringRef supplementaryFileMapPath =
569569
Args.getLastArgValue(options::OPT_supplementary_output_file_map);
570-
llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> buffer =
571-
llvm::MemoryBuffer::getFile(supplementaryFileMapPath);
570+
571+
unsigned BadFileDescriptorRetryCount = 0;
572+
if (const Arg *A = Args.getLastArg(options::OPT_bad_file_descriptor_retry_count)) {
573+
if (StringRef(A->getValue()).getAsInteger(10, BadFileDescriptorRetryCount)) {
574+
Diags.diagnose(SourceLoc(), diag::error_invalid_arg_value,
575+
A->getAsString(Args), A->getValue());
576+
return None;
577+
}
578+
}
579+
580+
llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> buffer = nullptr;
581+
for (unsigned I = 0; I < BadFileDescriptorRetryCount + 1; ++I) {
582+
buffer = llvm::MemoryBuffer::getFile(supplementaryFileMapPath);
583+
if (buffer)
584+
break;
585+
if (buffer.getError().value() != EBADF)
586+
break;
587+
}
572588
if (!buffer) {
573589
Diags.diagnose(SourceLoc(), diag::cannot_open_file,
574590
supplementaryFileMapPath, buffer.getError().message());

lib/Frontend/Frontend.cpp

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -657,8 +657,13 @@ Optional<ModuleBuffers> CompilerInstance::getInputBuffersIfPresent(
657657
// FIXME: Working with filenames is fragile, maybe use the real path
658658
// or have some kind of FileManager.
659659
using FileOrError = llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>;
660-
FileOrError inputFileOrErr = swift::vfs::getFileOrSTDIN(getFileSystem(),
661-
input.getFileName());
660+
FileOrError inputFileOrErr =
661+
swift::vfs::getFileOrSTDIN(getFileSystem(), input.getFileName(),
662+
/*FileSize*/-1,
663+
/*RequiresNullTerminator*/true,
664+
/*IsVolatile*/false,
665+
/*Bad File Descriptor Retry*/getInvocation().getFrontendOptions()
666+
.BadFileDescriptorRetryCount);
662667
if (!inputFileOrErr) {
663668
Diagnostics.diagnose(SourceLoc(), diag::error_open_input_file,
664669
input.getFileName(),

0 commit comments

Comments
 (0)