From b91a5d5576f9df54ab64365620ef412b60e5aba2 Mon Sep 17 00:00:00 2001 From: sophia Date: Fri, 13 Jan 2023 11:46:00 -0800 Subject: [PATCH] Add file mutex util module --- lib/vagrant/action/builtin/box_add.rb | 32 ++++++++++++--------------- lib/vagrant/errors.rb | 4 ++++ lib/vagrant/util.rb | 1 + lib/vagrant/util/file_mutex.rb | 29 ++++++++++++++++++++++++ templates/locales/en.yml | 5 +++++ 5 files changed, 53 insertions(+), 18 deletions(-) create mode 100644 lib/vagrant/util/file_mutex.rb diff --git a/lib/vagrant/action/builtin/box_add.rb b/lib/vagrant/action/builtin/box_add.rb index 80d5b10ce..3b5624c4f 100644 --- a/lib/vagrant/action/builtin/box_add.rb +++ b/lib/vagrant/action/builtin/box_add.rb @@ -6,6 +6,7 @@ require "uri" require "vagrant/box_metadata" require "vagrant/util/downloader" require "vagrant/util/file_checksum" +require "vagrant/util/file_mutex" require "vagrant/util/platform" module Vagrant @@ -22,10 +23,6 @@ module Vagrant # file already exists. RESUME_DELAY = 24 * 60 * 60 - # When a box file is being downloaded, identify the download is in progress - # by Vagrant with a mutex file named . - MUTEX_SUFFIX = ".lock" - def initialize(app, env) @app = app @logger = Log4r::Logger.new("vagrant::action::builtin::box_add") @@ -482,25 +479,24 @@ module Vagrant end end - mutex_path = d.destination + MUTEX_SUFFIX - if File.file?(mutex_path) + begin + mutex_path = d.destination + ".lock" + Util::FileMutex.new(mutex_path).with_lock do + begin + d.download! + rescue Errors::DownloaderInterrupted + # The downloader was interrupted, so just return, because that + # means we were interrupted as well. + @download_interrupted = true + env[:ui].info(I18n.t("vagrant.actions.box.download.interrupted")) + end + end + rescue Errors::VagrantLocked raise Errors::DownloadAlreadyInProgress, dest_path: d.destination, lock_file_path: mutex_path end - begin - File.write(mutex_path, "") - d.download! - rescue Errors::DownloaderInterrupted - # The downloader was interrupted, so just return, because that - # means we were interrupted as well. - @download_interrupted = true - env[:ui].info(I18n.t("vagrant.actions.box.download.interrupted")) - ensure - File.delete(mutex_path) - end - Pathname.new(d.destination) end diff --git a/lib/vagrant/errors.rb b/lib/vagrant/errors.rb index 186de6865..8e6bb8989 100644 --- a/lib/vagrant/errors.rb +++ b/lib/vagrant/errors.rb @@ -924,6 +924,10 @@ module Vagrant error_key(:uploader_interrupted) end + class VagrantLocked < VagrantError + error_key(:vagrant_locked) + end + class VagrantInterrupt < VagrantError error_key(:interrupted) end diff --git a/lib/vagrant/util.rb b/lib/vagrant/util.rb index 4b3e0ff09..8e3cbd2af 100644 --- a/lib/vagrant/util.rb +++ b/lib/vagrant/util.rb @@ -20,6 +20,7 @@ module Vagrant autoload :Experimental, 'vagrant/util/experimental' autoload :FileChecksum, 'vagrant/util/file_checksum' autoload :FileMode, 'vagrant/util/file_mode' + autoload :FileMutex, 'vagrant/util/file_mutex' autoload :GuestHosts, 'vagrant/util/guest_hosts' autoload :GuestInspection, 'vagrant/util/guest_inspection' autoload :HashWithIndifferentAccess, 'vagrant/util/hash_with_indifferent_access' diff --git a/lib/vagrant/util/file_mutex.rb b/lib/vagrant/util/file_mutex.rb new file mode 100644 index 000000000..c005a23a6 --- /dev/null +++ b/lib/vagrant/util/file_mutex.rb @@ -0,0 +1,29 @@ +module Vagrant + module Util + class FileMutex + def initialize(mutex_path) + @mutex_path = mutex_path + end + + def with_lock(&block) + lock + block.call + ensure + unlock + end + + def lock + if File.file?(@mutex_path) + raise Errors::VagrantLocked, + lock_file_path: @mutex_path + end + + File.write(@mutex_path, "") + end + + def unlock + File.delete(@mutex_path) + end + end + end +end diff --git a/templates/locales/en.yml b/templates/locales/en.yml index 095f83384..4a18ff7f6 100644 --- a/templates/locales/en.yml +++ b/templates/locales/en.yml @@ -1675,6 +1675,11 @@ en: uploader_interrupted: |- The upload was interrupted by an external signal. It did not complete. + vagrant_locked: |- + The requested Vagrant action is locked. This may be caused + by other Vagrant processes attempting to do a similar action. + + Lock file path: %{lock_file_path} vagrantfile_exists: |- `Vagrantfile` already exists in this directory. Remove it before running `vagrant init`.