diff --git a/lib/vagrant/util/subprocess.rb b/lib/vagrant/util/subprocess.rb index 3737d3897..fdaf3564e 100644 --- a/lib/vagrant/util/subprocess.rb +++ b/lib/vagrant/util/subprocess.rb @@ -35,6 +35,26 @@ module Vagrant @logger = Log4r::Logger.new("vagrant::util::subprocess") end + # @return [TrueClass, FalseClass] subprocess is currently running + def running? + !!(@process && @process.alive?) + end + + # Stop the subprocess if running + # + # @return [TrueClass] FalseClass] true if process was running and stopped + def stop + if @process && @process.alive? + @process.stop + true + else + false + end + end + + # Start the process + # + # @return [Result] def execute # Get the timeout, if we have one timeout = @options[:timeout] @@ -62,7 +82,7 @@ module Vagrant # Build the ChildProcess @logger.info("Starting process: #{@command.inspect}") - process = ChildProcess.build(*@command) + @process = process = ChildProcess.build(*@command) # Create the pipes so we can read the output in real time as # we execute the command. diff --git a/test/unit/vagrant/util/subprocess_test.rb b/test/unit/vagrant/util/subprocess_test.rb index 3934d1a3c..c3686db76 100644 --- a/test/unit/vagrant/util/subprocess_test.rb +++ b/test/unit/vagrant/util/subprocess_test.rb @@ -47,4 +47,64 @@ describe Vagrant::Util::Subprocess do expect(result.stdout).to eq(data) end end + + describe "#running?" do + context "when subprocess has not been started" do + it "should return false" do + sp = described_class.new("ls") + expect(sp.running?).to be_false + end + end + context "when subprocess has completed" do + it "should return false" do + sp = described_class.new("ls") + sp.execute + expect(sp.running?).to be_false + end + end + context "when subprocess is running" do + it "should return true" do + sp = described_class.new("sleep", "0.2") + thread = Thread.new{ sp.execute } + sleep(0.1) + expect(sp.running?).to be_true + thread.join + end + end + end + + describe "#stop" do + context "when subprocess has not been started" do + it "should return false" do + sp = described_class.new("ls") + expect(sp.stop).to be_false + end + end + + context "when subprocess has already completed" do + it "should return false" do + sp = described_class.new("ls") + sp.execute + expect(sp.stop).to be_false + end + end + + context "when subprocess is running" do + let(:sp){ described_class.new("sleep", "1") } + it "should return true" do + thread = Thread.new{ sp.execute } + sleep(0.1) + expect(sp.stop).to be_true + thread.join + end + + it "should stop the process" do + thread = Thread.new{ sp.execute } + sleep(0.1) + sp.stop + expect(sp.running?).to be_false + thread.join + end + end + end end