Index: include/lldb/Host/LockFile.h =================================================================== --- /dev/null +++ include/lldb/Host/LockFile.h @@ -0,0 +1,27 @@ +//===-- LockFile.h ----------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_Host_LockFile_h_ +#define liblldb_Host_LockFile_h_ + +#if defined(_WIN32) +#include "lldb/Host/windows/LockFileWindows.h" +namespace lldb_private +{ +typedef LockFileWindows LockFile; +} +#else +#include "lldb/Host/posix/LockFilePosix.h" +namespace lldb_private +{ +typedef LockFilePosix LockFile; +} +#endif + +#endif // liblldb_Host_LockFile_h_ Index: include/lldb/Host/LockFileBase.h =================================================================== --- /dev/null +++ include/lldb/Host/LockFileBase.h @@ -0,0 +1,73 @@ +//===-- LockFileBase.h ------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_Host_LockFileBase_h_ +#define liblldb_Host_LockFileBase_h_ + +#include "lldb/Core/Error.h" + +#include + +namespace lldb_private +{ + +class LockFileBase +{ +public: + virtual ~LockFileBase () = default; + + bool + IsLocked () const; + + Error + WriteLock (const uint64_t start, const uint64_t len); + Error + TryWriteLock (const uint64_t start, const uint64_t len); + + Error + ReadLock (const uint64_t start, const uint64_t len); + Error + TryReadLock (const uint64_t start, const uint64_t len); + + Error + Unlock (); + +protected: + using Locker = std::function; + + LockFileBase (int fd); + + virtual bool + IsValidFile () const; + + virtual Error + DoWriteLock (const uint64_t start, const uint64_t len) = 0; + virtual Error + DoTryWriteLock (const uint64_t start, const uint64_t len) = 0; + + virtual Error + DoReadLock (const uint64_t start, const uint64_t len) = 0; + virtual Error + DoTryReadLock (const uint64_t start, const uint64_t len) = 0; + + virtual Error + DoUnlock () = 0; + + Error + DoLock (const Locker &locker, const uint64_t start, const uint64_t len); + + int m_fd; // not owned. + bool m_locked; + uint64_t m_start; + uint64_t m_len; +}; + +} + +#endif Index: include/lldb/Host/posix/LockFilePosix.h =================================================================== --- /dev/null +++ include/lldb/Host/posix/LockFilePosix.h @@ -0,0 +1,42 @@ +//===-- LockFilePosix.h -----------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_Host_posix_LockFilePosix_h_ +#define liblldb_Host_posix_LockFilePosix_h_ + +#include "lldb/Host/LockFileBase.h" + +namespace lldb_private { + +class LockFilePosix : public LockFileBase +{ +public: + explicit LockFilePosix (int fd); + ~LockFilePosix (); + +protected: + Error + DoWriteLock (const uint64_t start, const uint64_t len) override; + + Error + DoTryWriteLock (const uint64_t start, const uint64_t len) override; + + Error + DoReadLock (const uint64_t start, const uint64_t len) override; + + Error + DoTryReadLock (const uint64_t start, const uint64_t len) override; + + Error + DoUnlock () override; +}; + +} // namespace lldb_private + +#endif // liblldb_Host_posix_LockFilePosix_h_ Index: include/lldb/Host/windows/LockFileWindows.h =================================================================== --- /dev/null +++ include/lldb/Host/windows/LockFileWindows.h @@ -0,0 +1,49 @@ +//===-- LockFileWindows.h ---------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_Host_posix_LockFileWindows_h_ +#define liblldb_Host_posix_LockFileWindows_h_ + +#include "lldb/Host/LockFileBase.h" +#include "lldb/Host/windows/windows.h" + +namespace lldb_private { + +class LockFileWindows : public LockFileBase +{ +public: + explicit LockFileWindows (int fd); + ~LockFileWindows (); + +protected: + Error + DoWriteLock (const uint64_t start, const uint64_t len) override; + + Error + DoTryWriteLock (const uint64_t start, const uint64_t len) override; + + Error + DoReadLock (const uint64_t start, const uint64_t len) override; + + Error + DoTryReadLock (const uint64_t start, const uint64_t len) override; + + Error + DoUnlock () override; + + bool + IsValidFile () const override; + +private: + HANDLE m_file; +}; + +} // namespace lldb_private + +#endif // liblldb_Host_posix_LockFileWindows_h_ Index: lldb.xcodeproj/project.pbxproj =================================================================== --- lldb.xcodeproj/project.pbxproj +++ lldb.xcodeproj/project.pbxproj @@ -98,6 +98,8 @@ 254FBB971A81B03100BD6378 /* SBLaunchInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 254FBB961A81B03100BD6378 /* SBLaunchInfo.h */; settings = {ATTRIBUTES = (Public, ); }; }; 254FBBA31A9166F100BD6378 /* SBAttachInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 254FBBA21A9166F100BD6378 /* SBAttachInfo.h */; settings = {ATTRIBUTES = (Public, ); }; }; 254FBBA51A91670E00BD6378 /* SBAttachInfo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 254FBBA41A91670E00BD6378 /* SBAttachInfo.cpp */; }; + 255EFF741AFABA720069F277 /* LockFileBase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 255EFF731AFABA720069F277 /* LockFileBase.cpp */; }; + 255EFF761AFABA950069F277 /* LockFilePosix.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 255EFF751AFABA950069F277 /* LockFilePosix.cpp */; }; 256CBDB11ADD0E1700BC6CDC /* NativeRegisterContextLinux_arm.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 256CBDAB1ADD0DB600BC6CDC /* NativeRegisterContextLinux_arm.cpp */; }; 256CBDB41ADD0EFD00BC6CDC /* RegisterContextPOSIXCore_arm.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 256CBDB21ADD0EFD00BC6CDC /* RegisterContextPOSIXCore_arm.cpp */; }; 256CBDB51ADD0EFD00BC6CDC /* RegisterContextPOSIXCore_arm.h in Headers */ = {isa = PBXBuildFile; fileRef = 256CBDB31ADD0EFD00BC6CDC /* RegisterContextPOSIXCore_arm.h */; }; @@ -1253,6 +1255,11 @@ 254FBBA21A9166F100BD6378 /* SBAttachInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SBAttachInfo.h; path = include/lldb/API/SBAttachInfo.h; sourceTree = ""; }; 254FBBA41A91670E00BD6378 /* SBAttachInfo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SBAttachInfo.cpp; path = source/API/SBAttachInfo.cpp; sourceTree = ""; }; 254FBBA61A91672800BD6378 /* SBAttachInfo.i */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c.preprocessed; path = SBAttachInfo.i; sourceTree = ""; }; + 255EFF6F1AFABA320069F277 /* LockFileWindows.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = LockFileWindows.h; path = include/lldb/Host/windows/LockFileWindows.h; sourceTree = ""; }; + 255EFF701AFABA320069F277 /* PipeWindows.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = PipeWindows.h; path = include/lldb/Host/windows/PipeWindows.h; sourceTree = ""; }; + 255EFF711AFABA4D0069F277 /* LockFileWindows.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LockFileWindows.cpp; path = source/Host/windows/LockFileWindows.cpp; sourceTree = ""; }; + 255EFF731AFABA720069F277 /* LockFileBase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = LockFileBase.cpp; sourceTree = ""; }; + 255EFF751AFABA950069F277 /* LockFilePosix.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = LockFilePosix.cpp; sourceTree = ""; }; 256CBDAB1ADD0DB600BC6CDC /* NativeRegisterContextLinux_arm.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = NativeRegisterContextLinux_arm.cpp; sourceTree = ""; }; 256CBDAC1ADD0DB600BC6CDC /* NativeRegisterContextLinux_arm.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = NativeRegisterContextLinux_arm.h; sourceTree = ""; }; 256CBDAD1ADD0DB600BC6CDC /* NativeRegisterContextLinux_arm64.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = NativeRegisterContextLinux_arm64.cpp; sourceTree = ""; }; @@ -4881,6 +4888,7 @@ 3FDFDDC4199D37BE009756A7 /* posix */ = { isa = PBXGroup; children = ( + 255EFF751AFABA950069F277 /* LockFilePosix.cpp */, AFDFDFD019E34D3400EAE509 /* ConnectionFileDescriptorPosix.cpp */, 3FDFDDC5199D37ED009756A7 /* FileSystem.cpp */, 3FDFE53019A292F0009756A7 /* HostInfoPosix.cpp */, @@ -4911,6 +4919,9 @@ 3FDFE53E19A2940E009756A7 /* windows */ = { isa = PBXGroup; children = ( + 255EFF711AFABA4D0069F277 /* LockFileWindows.cpp */, + 255EFF6F1AFABA320069F277 /* LockFileWindows.h */, + 255EFF701AFABA320069F277 /* PipeWindows.h */, 3FDFE54719A2946B009756A7 /* AutoHandle.h */, 3FDFE53F19A29448009756A7 /* Condition.cpp */, 3FDFE54819A2946B009756A7 /* editlinewin.h */, @@ -5039,6 +5050,7 @@ 69A01E1A1236C5D400C660B5 /* common */ = { isa = PBXGroup; children = ( + 255EFF731AFABA720069F277 /* LockFileBase.cpp */, 250D6AE11A9679270049CC70 /* FileSystem.cpp */, 33E5E8411A672A240024ED68 /* StringConvert.cpp */, 25420ED11A649D88009ADBCB /* PipeBase.cpp */, @@ -6014,6 +6026,7 @@ 2689FFFF13353DB600698AC0 /* BreakpointResolver.cpp in Sources */, 25420ECD1A6490B8009ADBCB /* OptionValueChar.cpp in Sources */, 2689000113353DB600698AC0 /* BreakpointResolverAddress.cpp in Sources */, + 255EFF741AFABA720069F277 /* LockFileBase.cpp in Sources */, 2689000313353DB600698AC0 /* BreakpointResolverFileLine.cpp in Sources */, AF20F76D1AF18FC700751A6E /* SBLanguageRuntime.cpp in Sources */, 26474CA818D0CB070073DEBA /* RegisterContextFreeBSD_i386.cpp in Sources */, @@ -6441,6 +6454,7 @@ 94EA27CE17DE91750070F505 /* LibCxxUnorderedMap.cpp in Sources */, 266DFE9713FD656E00D0C574 /* OperatingSystem.cpp in Sources */, 26954EBE1401EE8B00294D09 /* DynamicRegisterInfo.cpp in Sources */, + 255EFF761AFABA950069F277 /* LockFilePosix.cpp in Sources */, 26274FA714030F79006BA130 /* DynamicLoaderDarwinKernel.cpp in Sources */, 94FA3DE01405D50400833217 /* ValueObjectConstResultChild.cpp in Sources */, 3FDFED2819BA6D96009756A7 /* HostThread.cpp in Sources */, Index: source/Host/CMakeLists.txt =================================================================== --- source/Host/CMakeLists.txt +++ source/Host/CMakeLists.txt @@ -15,6 +15,7 @@ common/HostProcess.cpp common/HostThread.cpp common/IOObject.cpp + common/LockFileBase.cpp common/Mutex.cpp common/MonitoringProcessLauncher.cpp common/NativeBreakpoint.cpp @@ -58,6 +59,7 @@ windows/HostInfoWindows.cpp windows/HostProcessWindows.cpp windows/HostThreadWindows.cpp + windows/LockFileWindows.cpp windows/Mutex.cpp windows/PipeWindows.cpp windows/ProcessLauncherWindows.cpp @@ -72,6 +74,7 @@ posix/HostInfoPosix.cpp posix/HostProcessPosix.cpp posix/HostThreadPosix.cpp + posix/LockFilePosix.cpp posix/PipePosix.cpp ) Index: source/Host/common/LockFileBase.cpp =================================================================== --- /dev/null +++ source/Host/common/LockFileBase.cpp @@ -0,0 +1,124 @@ +//===-- LockFileBase.cpp ----------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "lldb/Host/LockFileBase.h" + +using namespace lldb; +using namespace lldb_private; + +namespace +{ + +Error +AlreadyLocked () +{ + return Error ("Already locked"); +} + +Error +NotLocked () +{ + return Error ("Not locked"); +} + +} + +LockFileBase::LockFileBase (int fd) : + m_fd (fd), + m_locked (false), + m_start (0), + m_len (0) +{ + +} + +bool +LockFileBase::IsLocked () const +{ + return m_locked; +} + +Error +LockFileBase::WriteLock (const uint64_t start, const uint64_t len) +{ + return DoLock ([&] (const uint64_t start, const uint64_t len) + { + return DoWriteLock (start, len); + }, start, len); +} + +Error +LockFileBase::TryWriteLock (const uint64_t start, const uint64_t len) +{ + return DoLock ([&] (const uint64_t start, const uint64_t len) + { + return DoTryWriteLock (start, len); + }, start, len); +} + +Error +LockFileBase::ReadLock (const uint64_t start, const uint64_t len) +{ + return DoLock ([&] (const uint64_t start, const uint64_t len) + { + return DoReadLock (start, len); + }, start, len); +} + +Error +LockFileBase::TryReadLock (const uint64_t start, const uint64_t len) +{ + return DoLock ([&] (const uint64_t start, const uint64_t len) + { + return DoTryReadLock (start, len); + }, start, len); + +} + +Error +LockFileBase::Unlock () +{ + if (!IsLocked ()) + return NotLocked (); + + const auto error = DoUnlock (); + if (error.Success ()) + { + m_locked = false; + m_start = 0; + m_len = 0; + } + return error; +} + +bool +LockFileBase::IsValidFile () const +{ + return m_fd != -1; +} + +Error +LockFileBase::DoLock (const Locker &locker, const uint64_t start, const uint64_t len) +{ + if (!IsValidFile ()) + return Error("File is invalid"); + + if (IsLocked ()) + return AlreadyLocked (); + + const auto error = locker (start, len); + if (error.Success ()) + { + m_locked = true; + m_start = start; + m_len = len; + } + + return error; +} Index: source/Host/posix/LockFilePosix.cpp =================================================================== --- /dev/null +++ source/Host/posix/LockFilePosix.cpp @@ -0,0 +1,77 @@ +//===-- LockFilePosix.cpp ---------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "lldb/Host/posix/LockFilePosix.h" + +#include + +using namespace lldb; +using namespace lldb_private; + +namespace +{ + +Error fileLock (int fd, int cmd, int lock_type, const uint64_t start, const uint64_t len) +{ + struct flock fl; + + fl.l_type = lock_type; + fl.l_whence = SEEK_SET; + fl.l_start = start; + fl.l_len = len; + fl.l_pid = ::getpid (); + + Error error; + if (::fcntl (fd, cmd, &fl) == -1) + error.SetErrorToErrno (); + + return error; +} + +} // namespace + +LockFilePosix::LockFilePosix (int fd) + : LockFileBase (fd) +{ +} + +LockFilePosix::~LockFilePosix () +{ + Unlock (); +} + +Error +LockFilePosix::DoWriteLock (const uint64_t start, const uint64_t len) +{ + return fileLock (m_fd, F_SETLKW, F_WRLCK, start, len); +} + +Error +LockFilePosix::DoTryWriteLock (const uint64_t start, const uint64_t len) +{ + return fileLock (m_fd, F_SETLK, F_WRLCK, start, len); +} + +Error +LockFilePosix::DoReadLock (const uint64_t start, const uint64_t len) +{ + return fileLock (m_fd, F_SETLKW, F_RDLCK, start, len); +} + +Error +LockFilePosix::DoTryReadLock (const uint64_t start, const uint64_t len) +{ + return fileLock (m_fd, F_SETLK, F_RDLCK, start, len); +} + +Error +LockFilePosix::DoUnlock () +{ + return fileLock (m_fd, F_SETLK, F_UNLCK, m_start, m_len); +} Index: source/Host/windows/LockFileWindows.cpp =================================================================== --- /dev/null +++ source/Host/windows/LockFileWindows.cpp @@ -0,0 +1,98 @@ +//===-- LockFileWindows.cpp -------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "lldb/Host/windows/LockFileWindows.h" + +#include + +using namespace lldb; +using namespace lldb_private; + +namespace +{ + +Error fileLock (HANDLE file_handle, DWORD flags, const uint64_t start, const uint64_t len) +{ + if (start != 0) + return Error ("Non-zero start lock regions are not supported"); + + OVERLAPPED overlapped = {0}; + + if (!::LockFileEx (file_handle, flags, 0, len, 0, &overlapped) && ::GetLastError () != ERROR_IO_PENDING) + return Error (::GetLastError (), eErrorTypeWin32); + + DWORD bytes; + if (!::GetOverlappedResult (file_handle, &overlapped, &bytes, TRUE)) + return Error (::GetLastError (), eErrorTypeWin32); + + return Error (); +} + +} // namespace + +LockFileWindows::LockFileWindows (int fd) + : LockFileBase (fd), + m_file (reinterpret_cast (_get_osfhandle (fd))) +{ +} + +LockFileWindows::~LockFileWindows () +{ + Unlock (); + if (m_file != INVALID_HANDLE_VALUE) + { + ::CloseHandle (m_file); + m_file = INVALID_HANDLE_VALUE; + } +} + +bool +LockFileWindows::IsValidFile () const +{ + return LockFileBase::IsValidFile() && m_file != INVALID_HANDLE_VALUE; +} + +Error +LockFileWindows::DoWriteLock (const uint64_t start, const uint64_t len) +{ + return fileLock (m_file, LOCKFILE_EXCLUSIVE_LOCK, start, len); +} + +Error +LockFileWindows::DoTryWriteLock (const uint64_t start, const uint64_t len) +{ + return fileLock (m_file, LOCKFILE_EXCLUSIVE_LOCK | LOCKFILE_FAIL_IMMEDIATELY, start, len); +} + +Error +LockFileWindows::DoReadLock (const uint64_t start, const uint64_t len) +{ + return fileLock (m_file, 0, start, len); +} + +Error +LockFileWindows::DoTryReadLock (const uint64_t start, const uint64_t len) +{ + return fileLock (m_file, LOCKFILE_FAIL_IMMEDIATELY, start, len); +} + +Error +LockFileWindows::DoUnlock () +{ + OVERLAPPED overlapped = {0}; + + if (!::UnlockFileEx (m_file, 0, m_len, 0, &overlapped) && ::GetLastError () != ERROR_IO_PENDING) + return Error (::GetLastError (), eErrorTypeWin32); + + DWORD bytes; + if (!::GetOverlappedResult (m_file, &overlapped, &bytes, TRUE)) + return Error (::GetLastError (), eErrorTypeWin32); + + return Error (); +} Index: source/Target/Platform.cpp =================================================================== --- source/Target/Platform.cpp +++ source/Target/Platform.cpp @@ -1840,16 +1840,8 @@ GetModuleCacheRoot (), GetCacheHostname (), module_spec, - [=](const ModuleSpec &module_spec, FileSpec &tmp_download_file_spec) + [=](const ModuleSpec &module_spec, const FileSpec &tmp_download_file_spec) { - // Get temporary file name for a downloaded module. - llvm::SmallString tmp_download_file_path; - const auto err_code = llvm::sys::fs::createTemporaryFile ( - "lldb", module_spec.GetUUID ().GetAsString ().c_str (), tmp_download_file_path); - if (err_code) - return Error ("Failed to create temp file: %s", err_code.message ().c_str ()); - - tmp_download_file_spec.SetFile (tmp_download_file_path.c_str (), true); return DownloadModuleSlice (module_spec.GetFileSpec (), module_spec.GetObjectOffset (), module_spec.GetObjectSize (), Index: source/Utility/ModuleCache.h =================================================================== --- source/Utility/ModuleCache.h +++ source/Utility/ModuleCache.h @@ -14,6 +14,7 @@ #include "lldb/lldb-forward.h" #include "lldb/Core/Error.h" +#include "lldb/Host/File.h" #include "lldb/Host/FileSpec.h" #include @@ -45,9 +46,18 @@ class ModuleCache { public: - using Downloader = std::function; + using Downloader = std::function; Error + GetAndPut(const FileSpec &root_dir_spec, + const char *hostname, + const ModuleSpec &module_spec, + const Downloader &downloader, + lldb::ModuleSP &cached_module_sp, + bool *did_create_ptr); + +private: + Error Put (const FileSpec &root_dir_spec, const char *hostname, const ModuleSpec &module_spec, @@ -60,15 +70,6 @@ lldb::ModuleSP &cached_module_sp, bool *did_create_ptr); - Error - GetAndPut(const FileSpec &root_dir_spec, - const char *hostname, - const ModuleSpec &module_spec, - const Downloader &downloader, - lldb::ModuleSP &cached_module_sp, - bool *did_create_ptr); - -private: static FileSpec GetModuleDirectory (const FileSpec &root_dir_spec, const UUID &uuid); Index: source/Utility/ModuleCache.cpp =================================================================== --- source/Utility/ModuleCache.cpp +++ source/Utility/ModuleCache.cpp @@ -11,20 +11,24 @@ #include "lldb/Core/Module.h" #include "lldb/Core/ModuleSpec.h" +#include "lldb/Host/File.h" #include "lldb/Host/FileSystem.h" +#include "lldb/Host/LockFile.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/FileUtilities.h" #include #include -# + using namespace lldb; using namespace lldb_private; namespace { const char* kModulesSubdir = ".cache"; +const char* kLockFileName = ".lock"; +const char* kTempFileName = ".temp"; FileSpec JoinPath (const FileSpec &path1, const char* path2) @@ -58,21 +62,13 @@ const FileSpec &tmp_file) { const auto module_spec_dir = GetModuleDirectory (root_dir_spec, module_spec.GetUUID ()); - auto error = MakeDirectory (module_spec_dir); - if (error.Fail ()) - return error; - const auto module_file_path = JoinPath (module_spec_dir, module_spec.GetFileSpec ().GetFilename ().AsCString ()); const auto tmp_file_path = tmp_file.GetPath (); - const auto err_code = llvm::sys::fs::copy_file (tmp_file_path.c_str (), module_file_path.GetPath ().c_str ()); + const auto err_code = llvm::sys::fs::rename (tmp_file_path.c_str (), module_file_path.GetPath ().c_str ()); if (err_code) - { - error.SetErrorStringWithFormat ("failed to copy file %s to %s: %s", - tmp_file_path.c_str (), - module_file_path.GetPath ().c_str (), - err_code.message ().c_str ()); - } + return Error ("Failed to rename file %s to %s: %s", + tmp_file_path.c_str (), module_file_path.GetPath ().c_str (), err_code.message ().c_str ()); // Create sysroot link to a module. const auto sysroot_module_path_spec = GetHostSysRootModulePath (root_dir_spec, hostname, module_spec.GetFileSpec ()); @@ -99,7 +95,9 @@ const auto module_file_path = JoinPath (module_spec_dir, module_spec.GetFileSpec ().GetFilename ().AsCString ()); if (!module_file_path.Exists ()) - return Error ("module %s not found", module_file_path.GetPath ().c_str ()); + return Error ("Module %s not found", module_file_path.GetPath ().c_str ()); + if (module_file_path.GetByteSize () != module_spec.GetObjectSize ()) + return Error ("Module %s has invalid file size", module_file_path.GetPath ().c_str ()); // We may have already cached module but downloaded from an another host - in this case let's create a symlink to it. const auto sysroot_module_path_spec = GetHostSysRootModulePath (root_dir_spec, hostname, module_spec.GetFileSpec ()); @@ -127,34 +125,42 @@ lldb::ModuleSP &cached_module_sp, bool *did_create_ptr) { + const auto module_spec_dir = GetModuleDirectory (root_dir_spec, module_spec.GetUUID ()); + auto error = MakeDirectory (module_spec_dir); + if (error.Fail ()) + return error; + + // Open lock file. + const auto lock_file_spec = JoinPath (module_spec_dir, kLockFileName); + File lock_file (lock_file_spec, File::eOpenOptionWrite | File::eOpenOptionCanCreate | File::eOpenOptionCloseOnExec); + if (!lock_file) + { + error.SetErrorToErrno (); + return Error("Failed to open lock file %s: %s", lock_file_spec.GetPath ().c_str (), error.AsCString ()); + } + LockFile lock (lock_file.GetDescriptor ()); + error = lock.WriteLock (0, 1); + if (error.Fail ()) + return Error("Failed to lock file %s:%s", lock_file_spec.GetPath ().c_str (), error.AsCString ()); + // Check local cache for a module. - auto error = Get (root_dir_spec, - hostname, - module_spec, - cached_module_sp, - did_create_ptr); + error = Get (root_dir_spec, hostname, module_spec, cached_module_sp, did_create_ptr); if (error.Success ()) return error; - FileSpec tmp_download_file_spec; + const auto tmp_download_file_spec = JoinPath (module_spec_dir, kTempFileName); error = downloader (module_spec, tmp_download_file_spec); llvm::FileRemover tmp_file_remover (tmp_download_file_spec.GetPath ().c_str ()); if (error.Fail ()) return Error("Failed to download module: %s", error.AsCString ()); // Put downloaded file into local module cache. - error = Put (root_dir_spec, - hostname, - module_spec, - tmp_download_file_spec); + error = Put (root_dir_spec, hostname, module_spec, tmp_download_file_spec); if (error.Fail ()) return Error ("Failed to put module into cache: %s", error.AsCString ()); - return Get (root_dir_spec, - hostname, - module_spec, - cached_module_sp, - did_create_ptr); + tmp_file_remover.releaseFile (); + return Get (root_dir_spec, hostname, module_spec, cached_module_sp, did_create_ptr); } FileSpec