From dc55c914e487bc6b3ccc1f3cbe5cf53c27bcb3bc Mon Sep 17 00:00:00 2001 From: Ray Ruvinskiy Date: Mon, 29 Sep 2014 16:47:29 -0400 Subject: [PATCH] Work around WaitForCommunicator lock race condition The LXC provider issues the "fetch_ip" action to look up the IP address of the container as part of its "ssh_info" action. Vagrant::LXC::Action.action_fetch_ip checks the machine state using Builtin::IsState, which calls Vagrant::Machine.state, which also updates the state in the machine index and acquires a machine index entry lock to do that. A race condition ensues in WaitForCommunicator.call, where ready_thr tries to acquire the machine index lock while running ssh_info, and states_thr tries to acquire the same lock doing its own state look up (env[:machine].state.id). If they both try to acquire the lock at the same time, one will fail, and an exception will be raised. Work around this issue by checking for the desired machine state (:running) in Vagrant::LXC::Provider.ssh_info, which can get the state from Vagrant::LXC::Provider.state, which in turn does not write out the state into the index file and does not acquire the index entry lock. --- lib/vagrant-lxc/action.rb | 11 +++-------- lib/vagrant-lxc/provider.rb | 4 ++-- 2 files changed, 5 insertions(+), 10 deletions(-) diff --git a/lib/vagrant-lxc/action.rb b/lib/vagrant-lxc/action.rb index b699c28..d021009 100644 --- a/lib/vagrant-lxc/action.rb +++ b/lib/vagrant-lxc/action.rb @@ -197,14 +197,9 @@ module Vagrant # is expected to be put into the `:machine_ip` key. def self.action_fetch_ip Builder.new.tap do |b| - b.use Builtin::ConfigValidate - b.use Builtin::Call, Builtin::IsState, :running do |env, b2| - if env[:result] - b2.use FetchIpWithLxcAttach if env[:machine].provider.driver.supports_attach? - b2.use FetchIpFromDnsmasqLeases - else - b2.use Builtin::Message, I18n.t("vagrant_lxc.messages.not_running") - end + b.use Builtin::Call, Builtin::ConfigValidate do |env, b2| + b2.use FetchIpWithLxcAttach if env[:machine].provider.driver.supports_attach? + b2.use FetchIpFromDnsmasqLeases end end end diff --git a/lib/vagrant-lxc/provider.rb b/lib/vagrant-lxc/provider.rb index 85ffd52..286f4d9 100644 --- a/lib/vagrant-lxc/provider.rb +++ b/lib/vagrant-lxc/provider.rb @@ -64,9 +64,9 @@ module Vagrant # Returns the SSH info for accessing the Container. def ssh_info - # If the Container is not created then we cannot possibly SSH into it, so + # If the Container is not running then we cannot possibly SSH into it, so # we return nil. - return nil if state == :not_created + return nil if state.id != :running # Run a custom action called "fetch_ip" which does what it says and puts # the IP found into the `:machine_ip` key in the environment.