summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/mixlib/shellout/windows.rb37
1 files changed, 35 insertions, 2 deletions
diff --git a/lib/mixlib/shellout/windows.rb b/lib/mixlib/shellout/windows.rb
index 6003ae8..fe7fd19 100644
--- a/lib/mixlib/shellout/windows.rb
+++ b/lib/mixlib/shellout/windows.rb
@@ -20,8 +20,14 @@
require 'win32/process'
require 'mixlib/shellout/windows/core_ext'
+require 'mixlib/log'
module Mixlib
+ class ShelloutLog
+ extend Mixlib::Log
+ init("#{ENV['temp']}/shellout.txt")
+ end
+
class ShellOut
module Windows
@@ -43,6 +49,7 @@ module Mixlib
# Missing lots of features from the UNIX version, such as
# uid, etc.
def run_command
+ logger = ShelloutLog.logger
#
# Create pipes to capture stdout and stderr,
@@ -90,6 +97,7 @@ module Mixlib
# Wait for the process to finish, consuming output as we go
#
start_wait = Time.now
+ logger.warn(Utils.format_process(process, app_name, command_line, timeout)) if logger
while true
wait_status = WaitForSingleObject(process.process_handle, 0)
case wait_status
@@ -107,12 +115,15 @@ module Mixlib
# Kill the process
if (Time.now - start_wait) > timeout
begin
+ require 'wmi-lite/wmi'
+ wmi = WmiLite::Wmi.new
+ Utils.kill_process_tree(process.process_id, wmi, logger)
Process.kill(:KILL, process.process_id)
- rescue Errno::EIO
+ rescue Errno::EIO, SystemCallError
logger.warn("Failed to kill timed out process #{process.process_id}") if logger
end
- raise Mixlib::ShellOut::CommandTimeout, "command timed out:\n#{format_for_exception}"
+ raise Mixlib::ShellOut::CommandTimeout, "command timed out:\n#{format_for_exception}\n#{Utils.format_process(process, app_name, command_line, timeout)}"
end
consume_output(open_streams, stdout_read, stderr_read)
@@ -313,6 +324,28 @@ module Mixlib
def self.executable?(path)
File.executable?(path) && !File.directory?(path)
end
+
+ def self.kill_process_tree(pid, wmi, logger)
+ wmi.query("select ProcessID, Name from Win32_Process where ParentProcessID=#{pid}").each do |instance|
+ child_pid = instance.wmi_ole_object.processid
+ kill_process_tree(child_pid, wmi, logger)
+ begin
+ logger.warn("killing child process #{child_pid}::#{instance.wmi_ole_object.Name} of parent #{pid}") if logger
+ Process.kill(:KILL, child_pid)
+ rescue Errno::EIO, SystemCallError
+ logger.warn("Failed to kill child process #{child_pid}::#{instance.wmi_ole_object.Name} of parent #{pid}") if logger
+ end
+ end
+ end
+
+ def self.format_process(process, app_name, command_line, timeout)
+ msg = []
+ msg << "ProcessId: #{process.process_id}"
+ msg << "app_name: #{app_name}"
+ msg << "command_line: #{command_line}"
+ msg << "timeout: #{timeout}"
+ msg.join("\n")
+ end
end
end # class
end