From deaa6ee9d9d7e0c59ebf9652b607f699ba6a2f73 Mon Sep 17 00:00:00 2001 From: Cyberarm Date: Sun, 30 Oct 2022 20:58:51 -0500 Subject: [PATCH] shelling out to 'ping' no longer spawns command prompts on windows --- Gemfile | 1 + Gemfile.lock | 3 +++ lib/api/server_list_server.rb | 24 ++++++++++++------ lib/background_worker.rb | 47 ++++++++++++++++++++++++++++++++--- lib/common.rb | 39 +++++++++++++++++++++++++++-- lib/pages/server_browser.rb | 1 + w3d_hub_linux_launcher.rb | 3 +++ 7 files changed, 106 insertions(+), 12 deletions(-) diff --git a/Gemfile b/Gemfile index 092f5ee..59f0ee1 100644 --- a/Gemfile +++ b/Gemfile @@ -10,6 +10,7 @@ gem "websocket-client-simple" gem "thread-local" gem "ircparser" gem "win32-security", platforms: [:x64_mingw, :mingw] +gem "win32-process", platforms: [:x64_mingw, :mingw] # group :windows_packaging do # gem "rake" diff --git a/Gemfile.lock b/Gemfile.lock index 6da53c9..eace382 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -32,6 +32,8 @@ GEM websocket-client-simple (0.6.0) event_emitter websocket + win32-process (0.10.0) + ffi (>= 1.0.0) win32-security (0.5.0) ffi ffi-win32-extensions @@ -51,6 +53,7 @@ DEPENDENCIES rexml thread-local websocket-client-simple + win32-process win32-security BUNDLED WITH diff --git a/lib/api/server_list_server.rb b/lib/api/server_list_server.rb index 1d22b98..dc02fe3 100644 --- a/lib/api/server_list_server.rb +++ b/lib/api/server_list_server.rb @@ -42,17 +42,27 @@ class W3DHub end def send_ping(force_ping = false) - return - if force_ping || Gosu.milliseconds - @last_pinged >= @ping_interval @last_pinged = Gosu.milliseconds - Thread.new do - ping = Net::Ping::External.new(@address) - @ping = (ping.duration * 1000.0).round if ping.ping? + W3DHub::BackgroundWorker.parallel_job( + lambda do + @ping = -1 - States::Interface.instance&.update_server_ping(self) - end + W3DHub.captured_commmand("ping #{@address} #{W3DHub.windows? ? '-n 3' : '-c 3'}") do |line| + if W3DHub.windows? && line =~ /Minimum|Maximum|Maximum/i + @ping = line.strip.split(",").last.split("=").last.sub("ms", "").to_i + elsif W3DHub.unix? && line.start_with?("rtt min/avg/max/mdev") + @ping = line.strip.split("=").last.split("/")[1].to_i + end + end + + @ping + end, + lambda do |_| + States::Interface.instance&.update_server_ping(self) + end + ) end end diff --git a/lib/background_worker.rb b/lib/background_worker.rb index 1b0b601..0fdfbb0 100644 --- a/lib/background_worker.rb +++ b/lib/background_worker.rb @@ -39,12 +39,18 @@ class W3DHub def self.kill! @@thread.kill + + @@instance.kill! end def self.job(job, callback, error_handler = nil) @@instance.add_job(Job.new(job: job, callback: callback, error_handler: error_handler)) end + def self.parallel_job(job, callback, error_handler = nil) + @@instance.add_parallel_job(Job.new(job: job, callback: callback, error_handler: error_handler)) + end + def self.foreground_job(job, callback, error_handler = nil) @@instance.add_job(Job.new(job: job, callback: callback, error_handler: error_handler, deliver_to_queue: true)) end @@ -52,9 +58,40 @@ class W3DHub def initialize @busy = false @jobs = [] + + # Jobs which are order independent + @parallel_busy = false + @thread_pool = [] + @parallel_jobs = [] + end + + def kill! + @thread_pool.each(&:kill) end def handle_jobs + 8.times do |i| + Thread.new do |thread| + @thread_pool << thread + + while BackgroundWorker.run? + job = @parallel_jobs.shift + + @parallel_busy = true + + begin + job&.do + rescue => e + job&.raise_error(e) + end + + @parallel_busy = !@parallel_jobs.empty? + + sleep 0.1 + end + end + end + while BackgroundWorker.run? job = @jobs.shift @@ -62,8 +99,8 @@ class W3DHub begin job&.do - rescue => error - job&.raise_error(error) + rescue => e + job&.raise_error(e) end @busy = !@jobs.empty? @@ -79,8 +116,12 @@ class W3DHub @jobs << job end + def add_parallel_job(job) + @parallel_jobs << job + end + def busy? - @busy + @busy || @parallel_busy end class Job diff --git a/lib/common.rb b/lib/common.rb index 87ed8ae..af37546 100644 --- a/lib/common.rb +++ b/lib/common.rb @@ -40,11 +40,46 @@ class W3DHub end end - def self.commmand(command) + def self.captured_commmand(command, &block) if windows? + stdout_read, stdout_write = IO.pipe + process_info = Process.create( + command_line: command, + creation_flags: Process::DETACHED_PROCESS, + process_inherit: true, + thread_inherit: true, + inherit: true, + startup_info: { + stdout: stdout_write, + stderr: stdout_write + } + ) + + pid = process_info.process_id + + until Process.get_exitcode(pid) + readable, _writable, _errorable = IO.select([stdout_read], [], [], 1) + + readable&.each do |io| + line = io.readpartial(1024) + + block&.call(line) + end + end + + stdout_read.close + stdout_write.close + + Process.get_exitcode(pid).zero? else - IO.popen(command) + IO.popen(command) do |io| + io.each_line do |line| + block&.call(line) + end + end + + $CHILD_STATUS.success? end end diff --git a/lib/pages/server_browser.rb b/lib/pages/server_browser.rb index b13cd6b..392b822 100644 --- a/lib/pages/server_browser.rb +++ b/lib/pages/server_browser.rb @@ -249,6 +249,7 @@ class W3DHub server_map.value = server&.status&.map player_count.value = "#{server&.status&.player_count}/#{server&.status&.max_players}" server_ping.value = ping_icon(server) + server_ping.parent.parent.tip = ping_tip(server) end def update_server_ping(server) diff --git a/w3d_hub_linux_launcher.rb b/w3d_hub_linux_launcher.rb index e23bded..e9d281f 100644 --- a/w3d_hub_linux_launcher.rb +++ b/w3d_hub_linux_launcher.rb @@ -68,6 +68,7 @@ end require "i18n" require "launchy" require "websocket-client-simple" +require "English" I18n.load_path << Dir["#{W3DHub::GAME_ROOT_PATH}/locales/*.yml"] I18n.default_locale = :en @@ -135,6 +136,8 @@ require_relative "lib/asterisk/states/game_form" require_relative "lib/asterisk/states/irc_profile_form" require_relative "lib/asterisk/states/server_profile_form" +require "win32/process" if W3DHub.windows? + logger.info(W3DHub::LOG_TAG) { "W3D Hub Linux Launcher v#{W3DHub::VERSION}" } Thread.new do