From 50a5bdf560c8ff01c54cf72c25c3b8e22937832c Mon Sep 17 00:00:00 2001 From: RittaNarita Date: Thu, 24 Sep 2015 17:59:10 +0900 Subject: [PATCH 1/9] fix signal and accept_nonblock to adapt to windows --- lib/serverengine.rb | 2 ++ lib/serverengine/daemon.rb | 2 +- lib/serverengine/process_manager.rb | 21 ++++++++++++++------- lib/serverengine/server.rb | 10 ++++++---- 4 files changed, 23 insertions(+), 12 deletions(-) diff --git a/lib/serverengine.rb b/lib/serverengine.rb index 6ead631..2180e4b 100644 --- a/lib/serverengine.rb +++ b/lib/serverengine.rb @@ -47,6 +47,8 @@ module ServerEngine require File.join(here, v) } + $platformwin = /mswin|mingw/ === RUBY_PLATFORM + def self.create(server_module, worker_module, load_config_proc={}, &block) Daemon.new(server_module, worker_module, load_config_proc, &block) end diff --git a/lib/serverengine/daemon.rb b/lib/serverengine/daemon.rb index fae187e..43fbcfa 100644 --- a/lib/serverengine/daemon.rb +++ b/lib/serverengine/daemon.rb @@ -51,7 +51,7 @@ def initialize(server_module, worker_module, load_config_proc={}, &block) module Signals GRACEFUL_STOP = :TERM - IMMEDIATE_STOP = :QUIT + IMMEDIATE_STOP = $platformwin ? :KILL : :QUIT GRACEFUL_RESTART = :USR1 IMMEDIATE_RESTART = :HUP RELOAD = :USR2 diff --git a/lib/serverengine/process_manager.rb b/lib/serverengine/process_manager.rb index ee91e83..b794127 100644 --- a/lib/serverengine/process_manager.rb +++ b/lib/serverengine/process_manager.rb @@ -52,9 +52,9 @@ def initialize(config={}) @closed = false @read_buffer = '' - if @auto_tick - TickThread.new(self) - end + end + if @auto_tick + TickThread.new(self) end attr_accessor :logger @@ -146,9 +146,12 @@ def spawn(*args) rpipe, wpipe = new_pipe_pair begin - options[[wpipe.fileno]] = wpipe - if @enable_heartbeat - env['SERVERENGINE_HEARTBEAT_PIPE'] = wpipe.fileno.to_s + + unless $platformwin + options[[wpipe.fileno]] = wpipe + if @enable_heartbeat + env['SERVERENGINE_HEARTBEAT_PIPE'] = wpipe.fileno.to_s + end end pid = Process.spawn(env, *args, options) @@ -211,7 +214,11 @@ def tick(blocking_timeout=0) if ready_pipes ready_pipes.each do |r| begin - r.read_nonblock(1024, @read_buffer) + if $platformwin + r.read(1024, @read_buffer) + 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..4625e7d 100644 --- a/lib/serverengine/server.rb +++ b/lib/serverengine/server.rb @@ -67,11 +67,13 @@ def install_signal_handlers 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 $platformwin + 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 From 1a983049f53b925d6b543d2617573a164c797456 Mon Sep 17 00:00:00 2001 From: RittaNarita Date: Wed, 30 Sep 2015 18:46:49 +0900 Subject: [PATCH 2/9] Windows8 doens't support SIGKILL --- lib/serverengine/daemon.rb | 2 +- lib/serverengine/multi_spawn_server.rb | 20 ++++++++++++++------ lib/serverengine/server.rb | 2 +- 3 files changed, 16 insertions(+), 8 deletions(-) diff --git a/lib/serverengine/daemon.rb b/lib/serverengine/daemon.rb index 43fbcfa..fae187e 100644 --- a/lib/serverengine/daemon.rb +++ b/lib/serverengine/daemon.rb @@ -51,7 +51,7 @@ def initialize(server_module, worker_module, load_config_proc={}, &block) module Signals GRACEFUL_STOP = :TERM - IMMEDIATE_STOP = $platformwin ? :KILL : :QUIT + IMMEDIATE_STOP = :QUIT GRACEFUL_RESTART = :USR1 IMMEDIATE_RESTART = :HUP RELOAD = :USR2 diff --git a/lib/serverengine/multi_spawn_server.rb b/lib/serverengine/multi_spawn_server.rb index 36dec33..f7ee460 100644 --- a/lib/serverengine/multi_spawn_server.rb +++ b/lib/serverengine/multi_spawn_server.rb @@ -19,12 +19,20 @@ 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 $platformwin + @pm = ProcessManager.new( + auto_tick: false, + graceful_kill_signal: Daemon::Signals::GRACEFUL_STOP, + 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/server.rb b/lib/serverengine/server.rb index 4625e7d..8bd14db 100644 --- a/lib/serverengine/server.rb +++ b/lib/serverengine/server.rb @@ -66,9 +66,9 @@ 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::DETACH) { s.stop(true) } unless $platformwin + 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 } From 5bf96ee73de924bb76859a154aa672f9ed823531 Mon Sep 17 00:00:00 2001 From: RittaNarita Date: Tue, 6 Oct 2015 23:32:31 +0900 Subject: [PATCH 3/9] Deleted needless change --- lib/serverengine/process_manager.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/serverengine/process_manager.rb b/lib/serverengine/process_manager.rb index b794127..51af39a 100644 --- a/lib/serverengine/process_manager.rb +++ b/lib/serverengine/process_manager.rb @@ -52,9 +52,9 @@ def initialize(config={}) @closed = false @read_buffer = '' - end - if @auto_tick - TickThread.new(self) + if @auto_tick + TickThread.new(self) + end end attr_accessor :logger From a87ab06305e7948c693d1c1ebfd64f482f35afb9 Mon Sep 17 00:00:00 2001 From: RittaNarita Date: Tue, 6 Oct 2015 23:59:51 +0900 Subject: [PATCH 4/9] Use ServerEngine.windows? instead of platformwin --- lib/serverengine.rb | 2 -- lib/serverengine/multi_spawn_server.rb | 2 +- lib/serverengine/process_manager.rb | 4 ++-- lib/serverengine/server.rb | 2 +- lib/serverengine/utils.rb | 7 +++++++ 5 files changed, 11 insertions(+), 6 deletions(-) diff --git a/lib/serverengine.rb b/lib/serverengine.rb index 2180e4b..6ead631 100644 --- a/lib/serverengine.rb +++ b/lib/serverengine.rb @@ -47,8 +47,6 @@ module ServerEngine require File.join(here, v) } - $platformwin = /mswin|mingw/ === RUBY_PLATFORM - def self.create(server_module, worker_module, load_config_proc={}, &block) Daemon.new(server_module, worker_module, load_config_proc, &block) end diff --git a/lib/serverengine/multi_spawn_server.rb b/lib/serverengine/multi_spawn_server.rb index f7ee460..433cbfa 100644 --- a/lib/serverengine/multi_spawn_server.rb +++ b/lib/serverengine/multi_spawn_server.rb @@ -19,7 +19,7 @@ module ServerEngine class MultiSpawnServer < MultiWorkerServer def initialize(worker_module, load_config_proc={}, &block) - if $platformwin + if ServerEngine.windows? @pm = ProcessManager.new( auto_tick: false, graceful_kill_signal: Daemon::Signals::GRACEFUL_STOP, diff --git a/lib/serverengine/process_manager.rb b/lib/serverengine/process_manager.rb index 51af39a..844c48d 100644 --- a/lib/serverengine/process_manager.rb +++ b/lib/serverengine/process_manager.rb @@ -147,7 +147,7 @@ def spawn(*args) begin - unless $platformwin + unless ServerEngine.windows? options[[wpipe.fileno]] = wpipe if @enable_heartbeat env['SERVERENGINE_HEARTBEAT_PIPE'] = wpipe.fileno.to_s @@ -214,7 +214,7 @@ def tick(blocking_timeout=0) if ready_pipes ready_pipes.each do |r| begin - if $platformwin + if ServerEngine.windows? r.read(1024, @read_buffer) else r.read_nonblock(1024, @read_buffer) diff --git a/lib/serverengine/server.rb b/lib/serverengine/server.rb index 8bd14db..79f279e 100644 --- a/lib/serverengine/server.rb +++ b/lib/serverengine/server.rb @@ -67,7 +67,7 @@ def install_signal_handlers SignalThread.new do |st| st.trap(Daemon::Signals::GRACEFUL_STOP) { s.stop(true) } st.trap(Daemon::Signals::DETACH) { s.stop(true) } - unless $platformwin + 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) } 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" From 78a87445379a22274d1736104c423137343c00c9 Mon Sep 17 00:00:00 2001 From: RittaNarita Date: Mon, 2 Nov 2015 17:24:43 +0900 Subject: [PATCH 5/9] Add Heartbeat pipe for windows --- lib/serverengine/process_manager.rb | 26 +++++++++++++++++++++++--- serverengine.gemspec | 3 +++ 2 files changed, 26 insertions(+), 3 deletions(-) diff --git a/lib/serverengine/process_manager.rb b/lib/serverengine/process_manager.rb index 844c48d..1dd941c 100644 --- a/lib/serverengine/process_manager.rb +++ b/lib/serverengine/process_manager.rb @@ -18,12 +18,17 @@ module ServerEngine require 'fcntl' + if ServerEngine.windows? + require 'win32/pipe' + include Win32 + end class ProcessManager def initialize(config={}) @monitors = [] @rpipes = {} @heartbeat_time = {} + @heartbeat_num = 0 @cloexec_mode = config[:cloexec_mode] @@ -147,7 +152,14 @@ def spawn(*args) begin - unless ServerEngine.windows? + if ServerEngine.windows? + @heartbeat_num += 1 + pipe_name = "SERVERENGINE_HEARTBEAT_PIPE_" + @heartbeat_num.to_s + rpipe = Pipe::Server.new(pipe_name, 0, Pipe::ACCESS_DUPLEX | 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 @@ -207,7 +219,12 @@ 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 @@ -215,7 +232,10 @@ def tick(blocking_timeout=0) ready_pipes.each do |r| begin if ServerEngine.windows? - r.read(1024, @read_buffer) + read_flag = r.read + if read_flag + @read_buffer = r.buffer + end else r.read_nonblock(1024, @read_buffer) end diff --git a/serverengine.gemspec b/serverengine.gemspec index cafc8cc..1c30ff0 100644 --- a/serverengine.gemspec +++ b/serverengine.gemspec @@ -20,6 +20,9 @@ Gem::Specification.new do |gem| gem.required_ruby_version = ">= 1.9.3" gem.add_dependency "sigdump", ["~> 0.2.2"] + if /mswin|mingw/ =~ RUBY_PLATFORM + gem.add_runtime_dependency("win32-pipe", ["~> 0.3.6"]) + end gem.add_development_dependency "rake", [">= 0.9.2"] gem.add_development_dependency "rspec", ["~> 2.13.0"] From 52f45e61ccd5f5b342293b5f4bbd78beda16b85c Mon Sep 17 00:00:00 2001 From: RittaNarita Date: Wed, 11 Nov 2015 00:11:26 +0900 Subject: [PATCH 6/9] Fix including Win32 --- lib/serverengine/process_manager.rb | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/serverengine/process_manager.rb b/lib/serverengine/process_manager.rb index 1dd941c..280c4e1 100644 --- a/lib/serverengine/process_manager.rb +++ b/lib/serverengine/process_manager.rb @@ -20,7 +20,6 @@ module ServerEngine require 'fcntl' if ServerEngine.windows? require 'win32/pipe' - include Win32 end class ProcessManager @@ -155,7 +154,7 @@ def spawn(*args) if ServerEngine.windows? @heartbeat_num += 1 pipe_name = "SERVERENGINE_HEARTBEAT_PIPE_" + @heartbeat_num.to_s - rpipe = Pipe::Server.new(pipe_name, 0, Pipe::ACCESS_DUPLEX | Pipe::FILE_FLAG_OVERLAPPED) + 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 From 90301448c23643964cd8c35a4cac5712793cc362 Mon Sep 17 00:00:00 2001 From: RittaNarita Date: Wed, 11 Nov 2015 00:22:39 +0900 Subject: [PATCH 7/9] Fix win32-pipe dependency --- serverengine.gemspec | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/serverengine.gemspec b/serverengine.gemspec index 1c30ff0..753855c 100644 --- a/serverengine.gemspec +++ b/serverengine.gemspec @@ -20,9 +20,7 @@ Gem::Specification.new do |gem| gem.required_ruby_version = ">= 1.9.3" gem.add_dependency "sigdump", ["~> 0.2.2"] - if /mswin|mingw/ =~ RUBY_PLATFORM - gem.add_runtime_dependency("win32-pipe", ["~> 0.3.6"]) - end + 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"] From f84595f48a7f25f54204438139837a3d8c859a37 Mon Sep 17 00:00:00 2001 From: RittaNarita Date: Wed, 11 Nov 2015 00:37:32 +0900 Subject: [PATCH 8/9] Fix Process Manager initialization to set immediate_kill_signal correctly --- lib/serverengine/multi_spawn_server.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/serverengine/multi_spawn_server.rb b/lib/serverengine/multi_spawn_server.rb index 433cbfa..cef1227 100644 --- a/lib/serverengine/multi_spawn_server.rb +++ b/lib/serverengine/multi_spawn_server.rb @@ -23,6 +23,7 @@ def initialize(worker_module, load_config_proc={}, &block) @pm = ProcessManager.new( auto_tick: false, graceful_kill_signal: Daemon::Signals::GRACEFUL_STOP, + immediate_kill_signal: false, enable_heartbeat: false, ) else From 45d00074711359f205ceb6619397ad423770a9a7 Mon Sep 17 00:00:00 2001 From: RittaNarita Date: Wed, 11 Nov 2015 00:42:44 +0900 Subject: [PATCH 9/9] Fix pipe_name setting to generate globally unique number --- lib/serverengine/process_manager.rb | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/lib/serverengine/process_manager.rb b/lib/serverengine/process_manager.rb index 280c4e1..96ef713 100644 --- a/lib/serverengine/process_manager.rb +++ b/lib/serverengine/process_manager.rb @@ -27,7 +27,6 @@ def initialize(config={}) @monitors = [] @rpipes = {} @heartbeat_time = {} - @heartbeat_num = 0 @cloexec_mode = config[:cloexec_mode] @@ -152,8 +151,7 @@ def spawn(*args) begin if ServerEngine.windows? - @heartbeat_num += 1 - pipe_name = "SERVERENGINE_HEARTBEAT_PIPE_" + @heartbeat_num.to_s + 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