summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorkaustubh-d <kausubh@clogeny.com>2013-07-23 04:57:47 -0700
committeradamedx <adamed@opscode.com>2013-08-04 08:27:07 -0700
commita3dbaab9287a2dce7d3c972dc54166b3c079d62e (patch)
tree17417c32e53f481dbc3e6444ca714af874d5d39a
parent126f8b7c1df884ccb55f1010ecca944e27a707be (diff)
downloadchef-a3dbaab9287a2dce7d3c972dc54166b3c079d62e.tar.gz
popen4 can yield while child has already died.
-rw-r--r--lib/chef/provider/cron.rb11
-rw-r--r--spec/unit/provider/cron_spec.rb17
2 files changed, 26 insertions, 2 deletions
diff --git a/lib/chef/provider/cron.rb b/lib/chef/provider/cron.rb
index 19fe9a64af..4430e3e18f 100644
--- a/lib/chef/provider/cron.rb
+++ b/lib/chef/provider/cron.rb
@@ -196,10 +196,17 @@ class Chef
end
def write_crontab(crontab)
+ write_exception = false
status = popen4("crontab -u #{@new_resource.user} -", :waitlast => true) do |pid, stdin, stdout, stderr|
- stdin.write crontab
+ begin
+ stdin.write crontab
+ rescue Errno::EPIPE => e
+ # popen4 could yield while child has already died.
+ write_exception = true
+ Chef::Log.debug("#{e.message}")
+ end
end
- if status.exitstatus > 0
+ if status.exitstatus > 0 || write_exception
raise Chef::Exceptions::Cron, "Error updating state of #{@new_resource.name}, exit: #{status.exitstatus}"
end
end
diff --git a/spec/unit/provider/cron_spec.rb b/spec/unit/provider/cron_spec.rb
index 56d51cd23f..f0d800741d 100644
--- a/spec/unit/provider/cron_spec.rb
+++ b/spec/unit/provider/cron_spec.rb
@@ -809,5 +809,22 @@ MAILTO=foo@example.com
@provider.send(:write_crontab, "Foo")
end.should raise_error(Chef::Exceptions::Cron, "Error updating state of #{@new_resource.name}, exit: 1")
end
+
+ it "should raise an exception if the command die's and parent tries to write" do
+ class WriteErrPipe
+ def write(str)
+ raise Errno::EPIPE, "Test"
+ end
+ end
+ @status.stub!(:exitstatus).and_return(1)
+ @provider.stub!(:popen4).and_yield(1234, WriteErrPipe.new, StringIO.new, StringIO.new).and_return(@status)
+
+ Chef::Log.should_receive(:debug).with("Broken pipe - Test")
+
+ lambda do
+ @provider.send(:write_crontab, "Foo")
+ end.should raise_error(Chef::Exceptions::Cron, "Error updating state of #{@new_resource.name}, exit: 1")
+ end
+
end
end