diff --git a/include/swift/Basic/LangOptions.h b/include/swift/Basic/LangOptions.h index 6516d7baeb234..7f6fa9ccd80bf 100644 --- a/include/swift/Basic/LangOptions.h +++ b/include/swift/Basic/LangOptions.h @@ -350,6 +350,9 @@ namespace swift { /// If set to \c false, fall back to the legacy manual reference name tracking code. bool EnableRequestBasedIncrementalDependencies = true; + /// Load swiftmodule files in memory as volatile and avoid mmap. + bool EnableVolatileModules = false; + /// Sets the target we are building for and updates platform conditions /// to match. /// diff --git a/include/swift/Option/FrontendOptions.td b/include/swift/Option/FrontendOptions.td index 496caa77100ea..1991a92762d4a 100644 --- a/include/swift/Option/FrontendOptions.td +++ b/include/swift/Option/FrontendOptions.td @@ -455,6 +455,9 @@ def warn_long_expression_type_checking_EQ : Joined<["-"], "warn-long-expression- def Rmodule_interface_rebuild : Flag<["-"], "Rmodule-interface-rebuild">, HelpText<"Emits a remark if an imported module needs to be re-compiled from its module interface">; +def enable_volatile_modules : Flag<["-"], "enable-volatile-modules">, + HelpText<"Load Swift modules in memory">; + def solver_expression_time_threshold_EQ : Joined<["-"], "solver-expression-time-threshold=">; def solver_disable_shrink : diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp index e629322648553..e707db8eda910 100644 --- a/lib/Frontend/CompilerInvocation.cpp +++ b/lib/Frontend/CompilerInvocation.cpp @@ -583,6 +583,8 @@ static bool ParseLangArgs(LangOptions &Opts, ArgList &Args, Opts.VerifyAllSubstitutionMaps |= Args.hasArg(OPT_verify_all_substitution_maps); + Opts.EnableVolatileModules |= Args.hasArg(OPT_enable_volatile_modules); + Opts.UseDarwinPreStableABIBit = (Target.isMacOSX() && Target.isMacOSXVersionLT(10, 14, 4)) || (Target.isiOS() && Target.isOSVersionLT(12, 2)) || diff --git a/lib/Serialization/SerializedModuleLoader.cpp b/lib/Serialization/SerializedModuleLoader.cpp index 0f6bba4d2532d..b39624b9a445d 100644 --- a/lib/Serialization/SerializedModuleLoader.cpp +++ b/lib/Serialization/SerializedModuleLoader.cpp @@ -337,8 +337,27 @@ std::error_code SerializedModuleLoaderBase::openModuleFile( } // Actually load the file and error out if necessary. + // + // Use the default arguments except for IsVolatile that is set by the + // frontend option -enable-volatile-modules. If set, we avoid the use of + // mmap to workaround issues on NFS when the swiftmodule file loaded changes + // on disk while it's in use. + // + // In practice, a swiftmodule file can chane when a client uses a + // swiftmodule file from a framework while the framework is recompiled and + // installed over existing files. Or when many processes rebuild the same + // module interface. + // + // We have seen these scenarios leading to deserialization errors that on + // the surface look like memory corruption. + // + // rdar://63755989 + bool enableVolatileModules = Ctx.LangOpts.EnableVolatileModules; llvm::ErrorOr> ModuleOrErr = - FS.getBufferForFile(ModulePath); + FS.getBufferForFile(ModulePath, + /*FileSize=*/-1, + /*RequiresNullTerminator=*/true, + /*IsVolatile=*/enableVolatileModules); if (!ModuleOrErr) return ModuleOrErr.getError();