diff --git a/lib/serverengine/multi_spawn_server.rb b/lib/serverengine/multi_spawn_server.rb index 36dec33..cef1227 100644 --- a/lib/serverengine/multi_spawn_server.rb +++ b/lib/serverengine/multi_spawn_server.rb @@ -19,12 +19,21 @@ module ServerEngine class MultiSpawnServer < MultiWorkerServer def initialize(worker_module, load_config_proc={}, &block) - @pm = ProcessManager.new( - auto_tick: false, - graceful_kill_signal: Daemon::Signals::GRACEFUL_STOP, - immediate_kill_signal: Daemon::Signals::IMMEDIATE_STOP, - enable_heartbeat: false, - ) + if ServerEngine.windows? + @pm = ProcessManager.new( + auto_tick: false, + graceful_kill_signal: Daemon::Signals::GRACEFUL_STOP, + immediate_kill_signal: false, + enable_heartbeat: false, + ) + else + @pm = ProcessManager.new( + auto_tick: false, + graceful_kill_signal: Daemon::Signals::GRACEFUL_STOP, + immediate_kill_signal: Daemon::Signals::IMMEDIATE_STOP, + enable_heartbeat: false, + ) + end super(worker_module, load_config_proc, &block) diff --git a/lib/serverengine/process_manager.rb b/lib/serverengine/process_manager.rb index ee91e83..96ef713 100644 --- a/lib/serverengine/process_manager.rb +++ b/lib/serverengine/process_manager.rb @@ -18,6 +18,9 @@ module ServerEngine require 'fcntl' + if ServerEngine.windows? + require 'win32/pipe' + end class ProcessManager def initialize(config={}) @@ -146,9 +149,18 @@ def spawn(*args) rpipe, wpipe = new_pipe_pair begin - options[[wpipe.fileno]] = wpipe - if @enable_heartbeat - env['SERVERENGINE_HEARTBEAT_PIPE'] = wpipe.fileno.to_s + + if ServerEngine.windows? + pipe_name = "SERVERENGINE_HEARTBEAT_PIPE_%016X" % Random.new.rand(2**128) + rpipe = Win32::Pipe::Server.new(pipe_name, 0, Win32::Pipe::ACCESS_DUPLEX | Win32::Pipe::FILE_FLAG_OVERLAPPED) + if @enable_heartbeat + env['SERVERENGINE_HEARTBEAT_PIPE'] = pipe_name + end + else + options[[wpipe.fileno]] = wpipe + if @enable_heartbeat + env['SERVERENGINE_HEARTBEAT_PIPE'] = wpipe.fileno.to_s + end end pid = Process.spawn(env, *args, options) @@ -204,14 +216,26 @@ def tick(blocking_timeout=0) return nil end - ready_pipes, _, _ = IO.select(@rpipes.keys, nil, nil, blocking_timeout) + if ServerEngine.windows? + # TODO: should use WaitForMultipleObjects? + ready_pipes = @rpipes.keys + else + ready_pipes, _, _ = IO.select(@rpipes.keys, nil, nil, blocking_timeout) + end time ||= Time.now if ready_pipes ready_pipes.each do |r| begin - r.read_nonblock(1024, @read_buffer) + if ServerEngine.windows? + read_flag = r.read + if read_flag + @read_buffer = r.buffer + end + else + r.read_nonblock(1024, @read_buffer) + end rescue Errno::EAGAIN, Errno::EINTR next rescue #EOFError diff --git a/lib/serverengine/server.rb b/lib/serverengine/server.rb index 0c9d6f1..79f279e 100644 --- a/lib/serverengine/server.rb +++ b/lib/serverengine/server.rb @@ -66,12 +66,14 @@ def install_signal_handlers s = self SignalThread.new do |st| st.trap(Daemon::Signals::GRACEFUL_STOP) { s.stop(true) } - st.trap(Daemon::Signals::IMMEDIATE_STOP) { s.stop(false) } - st.trap(Daemon::Signals::GRACEFUL_RESTART) { s.restart(true) } - st.trap(Daemon::Signals::IMMEDIATE_RESTART) { s.restart(false) } - st.trap(Daemon::Signals::RELOAD) { s.reload } st.trap(Daemon::Signals::DETACH) { s.stop(true) } - st.trap(Daemon::Signals::DUMP) { Sigdump.dump } + unless ServerEngine.windows? + st.trap(Daemon::Signals::IMMEDIATE_STOP) { s.stop(false) } + st.trap(Daemon::Signals::GRACEFUL_RESTART) { s.restart(true) } + st.trap(Daemon::Signals::IMMEDIATE_RESTART) { s.restart(false) } + st.trap(Daemon::Signals::RELOAD) { s.reload } + st.trap(Daemon::Signals::DUMP) { Sigdump.dump } + end end end diff --git a/lib/serverengine/utils.rb b/lib/serverengine/utils.rb index eb9cefd..f8a00c1 100644 --- a/lib/serverengine/utils.rb +++ b/lib/serverengine/utils.rb @@ -17,6 +17,13 @@ # module ServerEngine + IS_WINDOWS = /mswin|mingw/ === RUBY_PLATFORM + private_constant :IS_WINDOWS + + def self.windows? + IS_WINDOWS + end + module ClassMethods def dump_uncaught_error(e) STDERR.write "Unexpected error #{e}\n" diff --git a/serverengine.gemspec b/serverengine.gemspec index cafc8cc..753855c 100644 --- a/serverengine.gemspec +++ b/serverengine.gemspec @@ -20,6 +20,7 @@ Gem::Specification.new do |gem| gem.required_ruby_version = ">= 1.9.3" gem.add_dependency "sigdump", ["~> 0.2.2"] + gem.add_runtime_dependency("win32-pipe", ["~> 0.3.6"]) gem.add_development_dependency "rake", [">= 0.9.2"] gem.add_development_dependency "rspec", ["~> 2.13.0"]