lib/guard/spork/spork_instance.rb in guard-spork-1.1.0 vs lib/guard/spork/spork_instance.rb in guard-spork-1.2.0
- old
+ new
@@ -1,9 +1,9 @@
module Guard
class Spork
class SporkInstance
- attr_reader :type, :env, :port, :options, :pid
+ attr_reader :type, :env, :port, :options, :pid, :process
def initialize(type, port, env, options)
@type = type
@port = port
@env = env
@@ -24,28 +24,43 @@
type.to_s
end
end
def start
- @pid = fork do
- env_exec env, command
+ cmd = [command]
+
+ if self.class.windows?
+ cmd = ["cmd", "/C"] + cmd
end
+
+ @process = ChildProcess.build *cmd
+ @process.environment.merge!(env)
+ @process.io.inherit!
+ @process.start
+ @pid = @process.pid
end
def stop
- ::Process.kill('TERM', pid)
+ unless self.class.windows?
+ process.stop
+ else
+ kill_all_child_processes
+ end
end
def alive?
- return false unless pid
- ::Process.waitpid(pid, ::Process::WNOHANG).nil?
+ pid && process.alive?
end
def running?
- return false unless pid
+ return false unless alive?
TCPSocket.new('localhost', port).close
- true
+ if self.class.windows?
+ running_on_windows?
+ else
+ true
+ end
rescue Errno::ECONNREFUSED
false
end
def command
@@ -65,26 +80,46 @@
parts << "-p #{port}"
parts << "-q" if options[:quiet]
parts.join(" ")
end
- def env_exec(environment, command)
- if RUBY_VERSION > "1.9"
- exec environment, command
- else
- environment.each_pair { |key, value| ENV[key] = value }
- exec command
- end
+ def self.windows?
+ RUBY_PLATFORM =~ /mswin|msys|mingw/
end
private
def use_bundler?
options[:bundler]
end
def use_foreman?
options[:foreman]
+ end
+
+ def kill_all_child_processes
+ all_pids_for(pid).each do |pid|
+ Process.kill 9, pid
+ end
+ end
+
+ def all_pids_for(parent_pid)
+ pids = [parent_pid]
+ Sys::ProcTable.ps do |process|
+ pids += all_pids_for(process.pid) if process.ppid == parent_pid
+ end
+ pids
+ end
+
+ def running_on_windows?
+ DRb.start_service
+ # make sure that ringfinger is not taken from cache, because it won't
+ # work after guard-spork has been restarted
+ Rinda::RingFinger.class_variable_set :@@finger, nil
+ ts = Rinda::RingFinger.primary
+ ts.read_all([:name, :MagazineSlave, nil, nil]).size > 0
+ rescue DRb::DRbConnError
+ false
end
end
end
end