summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorMarkus Roberts <Markus@reality.com>2009-12-22 13:35:04 -0800
committerJames Turnbull <james@lovedthanlost.net>2009-12-23 09:50:49 +1100
commit6ab2453d966d1d48e12d8a8cec34b9e460597d04 (patch)
tree19bef07cb9eda8a0fc0ee0452a7214e617d391fd /lib
parent0e5d2647bd5f515dbaacf45f9e7dda5c27eb465a (diff)
downloadpuppet-6ab2453d966d1d48e12d8a8cec34b9e460597d04.tar.gz
puppet-6ab2453d966d1d48e12d8a8cec34b9e460597d04.tar.xz
puppet-6ab2453d966d1d48e12d8a8cec34b9e460597d04.zip
Fix for #2731 (problem communicating with processes in SELinux)
In some cases communicating with child processes via temprary files is not viable. This is Ricky Zhou's patch from the ticket, which solves the problem by using the more normal system of pipes. It is a broader reaching change than suggested by the ticket (it affects all execs, not just SELinux) but IMHO is the right way to go. Signed-off-by: Markus Roberts <Markus@reality.com>
Diffstat (limited to 'lib')
-rw-r--r--lib/puppet/util.rb73
1 files changed, 22 insertions, 51 deletions
diff --git a/lib/puppet/util.rb b/lib/puppet/util.rb
index 21573d1da..dd6ae69fa 100644
--- a/lib/puppet/util.rb
+++ b/lib/puppet/util.rb
@@ -259,28 +259,17 @@ module Util
@@os ||= Facter.value(:operatingsystem)
output = nil
child_pid, child_status = nil
- # There are problems with read blocking with badly behaved children
- # read.partialread doesn't seem to capture either stdout or stderr
- # We hack around this using a temporary file
-
- # The idea here is to avoid IO#read whenever possible.
- output_file="/dev/null"
- error_file="/dev/null"
- if ! arguments[:squelch]
- require "tempfile"
- output_file = Tempfile.new("puppet")
- if arguments[:combine]
- error_file=output_file
- end
- end
+ output_read, output_write = IO.pipe
oldverb = $VERBOSE
$VERBOSE = nil
child_pid = Kernel.fork
$VERBOSE = oldverb
if child_pid
+ output_write.close
# Parent process executes this
- child_status = (Process.waitpid2(child_pid)[1]).to_i >> 8
+ Process.waitpid(child_pid)
+ child_status = $?.exitstatus
else
# Child process executes this
Process.setsid
@@ -288,10 +277,18 @@ module Util
if arguments[:stdinfile]
$stdin.reopen(arguments[:stdinfile])
else
- $stdin.reopen("/dev/null")
+ $stdin.close
+ end
+ if arguments[:squelch]
+ $stdout.close
+ else
+ $stdout.reopen(output_write)
+ end
+ if arguments[:combine]
+ $stderr.reopen(output_write)
+ else
+ $stderr.close
end
- $stdout.reopen(output_file)
- $stderr.reopen(error_file)
3.upto(256){|fd| IO::new(fd).close rescue nil}
if arguments[:gid]
@@ -303,43 +300,17 @@ module Util
Process.uid = arguments[:uid] unless @@os == "Darwin"
end
ENV['LANG'] = ENV['LC_ALL'] = ENV['LC_MESSAGES'] = ENV['LANGUAGE'] = 'C'
- if command.is_a?(Array)
- Kernel.exec(*command)
- else
- Kernel.exec(command)
- end
+ Kernel.exec(*command)
rescue => detail
- puts detail.to_s
+ puts detail
exit!(1)
- end # begin; rescue
- end # if child_pid
+ end
+ end
# read output in if required
if ! arguments[:squelch]
-
- # Make sure the file's actually there. This is
- # basically a race condition, and is probably a horrible
- # way to handle it, but, well, oh well.
- unless FileTest.exists?(output_file.path)
- Puppet.warning "sleeping"
- sleep 0.5
- unless FileTest.exists?(output_file.path)
- Puppet.warning "sleeping 2"
- sleep 1
- unless FileTest.exists?(output_file.path)
- Puppet.warning "Could not get output"
- output = ""
- end
- end
- end
- unless output
- # We have to explicitly open here, so that it reopens
- # after the child writes.
- output = output_file.open.read
-
- # The 'true' causes the file to get unlinked right away.
- output_file.close(true)
- end
+ output = output_read.read
+ output_read.close
end
if arguments[:failonfail]
@@ -348,7 +319,7 @@ module Util
end
end
- return output
+ output
end
module_function :execute