summaryrefslogtreecommitdiff
path: root/lib/chef/application.rb
diff options
context:
space:
mode:
authorClaire McQuin <claire@getchef.com>2014-09-22 15:31:47 -0700
committerClaire McQuin <claire@getchef.com>2014-10-01 14:31:05 -0700
commit97b628a766d14a6a8fe6b3b2febb604a570e0cde (patch)
tree29f7f11b43250010a8e71c787c8d01eae0f1b97a /lib/chef/application.rb
parent00ecc94e206da3c09cf5dac8d698deaba970d8b2 (diff)
downloadchef-97b628a766d14a6a8fe6b3b2febb604a570e0cde.tar.gz
Disable unforked interval runs.
Clarify error message. Move fork and interval logic to application (specs pending). Clean code logic, fix specs. Allow unforked client runs with daemonize or splay
Diffstat (limited to 'lib/chef/application.rb')
-rw-r--r--lib/chef/application.rb46
1 files changed, 45 insertions, 1 deletions
diff --git a/lib/chef/application.rb b/lib/chef/application.rb
index 0430d4acfa..c007867f2b 100644
--- a/lib/chef/application.rb
+++ b/lib/chef/application.rb
@@ -206,12 +206,56 @@ class Chef::Application
)
@chef_client_json = nil
- @chef_client.run
+ if Chef::Config[:client_fork]
+ fork_chef_client # allowed to run client in forked process
+ else
+ @chef_client.run
+ end
@chef_client = nil
end
end
private
+ def fork_chef_client
+ # win32-process gem exposes some form of :fork for Process
+ # class. So we are seperately ensuring that the platform we're
+ # running on is not windows before forking.
+ if(Process.respond_to?(:fork) && !Chef::Platform.windows?)
+ Chef::Log.info "Forking chef instance to converge..."
+ pid = fork do
+ [:INT, :TERM].each {|s| trap(s, "EXIT") }
+ client_solo = Chef::Config[:solo] ? "chef-solo" : "chef-client"
+ $0 = "#{client_solo} worker: ppid=#{Process.ppid};start=#{Time.new.strftime("%R:%S")};"
+ begin
+ Chef::Log.debug "Forked instance now converging"
+ @chef_client.run
+ rescue Exception => e
+ Chef::Log.error(e.to_s)
+ exit 1
+ else
+ exit 0
+ end
+ end
+ Chef::Log.debug "Fork successful. Waiting for new chef pid: #{pid}"
+ result = Process.waitpid2(pid)
+ handle_child_exit(result)
+ Chef::Log.debug "Forked instance successfully reaped (pid: #{pid})"
+ true
+ else
+ @chef_client.run
+ end
+ end
+
+ def handle_child_exit(pid_and_status)
+ status = pid_and_status[1]
+ return true if status.success?
+ message = if status.signaled?
+ "Chef run process terminated by signal #{status.termsig} (#{Signal.list.invert[status.termsig]})"
+ else
+ "Chef run process exited unsuccessfully (exit code #{status.exitstatus})"
+ end
+ raise Exceptions::ChildConvergeError, message
+ end
def apply_config(config_content, config_file_path)
Chef::Config.from_string(config_content, config_file_path)