From 7d55f79caf66d04c645e14e84eec72ac54f3ef2e Mon Sep 17 00:00:00 2001 From: Takuro Ashie Date: Mon, 8 Aug 2022 16:57:25 +0900 Subject: [PATCH 1/2] Remove dependency to win32-api gem Recently we fail to load win32-api on Ruby 3.2-dev: https://github.com/fluent/fluentd/runs/7660210030?check_suite_focus=true D:/rubyinstaller-head-x64/lib/ruby/gems/3.2.0+2/gems/windows-api-0.4.5/lib/windows/api.rb:335:in `initialize': uninitialized constant Win32::API (NameError) @api = Win32::API.new(func, proto, rtype, dll) ^^^^^ from D:/rubyinstaller-head-x64/lib/ruby/gems/3.2.0+2/gems/windows-pr-1.2.6/lib/windows/msvcrt/string.rb:12:in `new' but Fluentd doesn't seem depend on win32-api so much. Using Fiddle is enough instead. It's time to drop win32-api gem. Signed-off-by: Takuro Ashie --- fluentd.gemspec | 3 --- lib/fluent/command/fluentd.rb | 7 +------ lib/fluent/plugin/file_wrapper.rb | 32 +++++++++++++++++++++++-------- lib/fluent/supervisor.rb | 9 ++------- lib/fluent/winsvc.rb | 10 ++-------- test/plugin/test_file_wrapper.rb | 5 ----- 6 files changed, 29 insertions(+), 37 deletions(-) diff --git a/fluentd.gemspec b/fluentd.gemspec index 83c5abc18d..43e8ae07bb 100644 --- a/fluentd.gemspec +++ b/fluentd.gemspec @@ -34,12 +34,9 @@ Gem::Specification.new do |gem| fake_platform = ENV['GEM_BUILD_FAKE_PLATFORM'].to_s gem.platform = fake_platform unless fake_platform.empty? if /mswin|mingw/ =~ fake_platform || (/mswin|mingw/ =~ RUBY_PLATFORM && fake_platform.empty?) - gem.add_runtime_dependency("win32-api", [">= 1.10", "< 2.0.0"]) gem.add_runtime_dependency("win32-service", ["~> 2.3.0"]) gem.add_runtime_dependency("win32-ipc", ["~> 0.7.0"]) gem.add_runtime_dependency("win32-event", ["~> 0.6.3"]) - gem.add_runtime_dependency("windows-api", ["~> 0.4.5"]) - gem.add_runtime_dependency("windows-pr", ["~> 1.2.6"]) gem.add_runtime_dependency("certstore_c", ["~> 0.1.7"]) end diff --git a/lib/fluent/command/fluentd.rb b/lib/fluent/command/fluentd.rb index 2150ece521..088af53b8b 100644 --- a/lib/fluent/command/fluentd.rb +++ b/lib/fluent/command/fluentd.rb @@ -189,9 +189,6 @@ } if Fluent.windows? - require 'windows/library' - include Windows::Library - opts.merge!( :winsvc_name => 'fluentdwinsvc', :winsvc_display_name => 'Fluentd Windows Service', @@ -292,9 +289,7 @@ case winsvcinstmode when 'i' binary_path = File.join(File.dirname(__FILE__), "..") - ruby_path = "\0" * 256 - GetModuleFileName.call(0,ruby_path,256) - ruby_path = ruby_path.rstrip.gsub(/\\/, '/') + ruby_path = ServerEngine.ruby_bin_path start_type = Service::DEMAND_START if opts[:regwinsvcautostart] start_type = Service::AUTO_START diff --git a/lib/fluent/plugin/file_wrapper.rb b/lib/fluent/plugin/file_wrapper.rb index 0ef875b14e..e99928b11a 100644 --- a/lib/fluent/plugin/file_wrapper.rb +++ b/lib/fluent/plugin/file_wrapper.rb @@ -35,20 +35,36 @@ def self.stat(path) end end - class WindowsFile - require 'windows/file' - require 'windows/handle' + module Win32API + require 'fiddle/import' + require 'fiddle/types' + extend Fiddle::Importer + + if RUBY_PLATFORM.split('-')[-1] == "ucrt" + MSVCRT_DLL = 'ucrtbase.dll' + else + MSVCRT_DLL = 'msvcrt.dll' + end + dlload MSVCRT_DLL, "kernel32.dll" + include Fiddle::Win32Types + + extern "intptr_t _get_osfhandle(int)" + extern "BOOL GetFileInformationByHandle(HANDLE, void *)" + extern "BOOL GetFileInformationByHandleEx(HANDLE, int, void *, DWORD)" + end + + class WindowsFile include File::Constants - include Windows::File - include Windows::Handle attr_reader :io + INVALID_HANDLE_VALUE = -1 + def initialize(path, mode='r') @path = path @io = File.open(path, mode2flags(mode)) - @file_handle = _get_osfhandle(@io.to_i) + @file_handle = Win32API._get_osfhandle(@io.to_i) @io.instance_variable_set(:@file_index, self.ino) def @io.ino @file_index @@ -68,7 +84,7 @@ def close def ino by_handle_file_information = '\0'*(4+8+8+8+4+4+4+4+4+4) #72bytes - unless GetFileInformationByHandle.call(@file_handle, by_handle_file_information) + unless Win32API.GetFileInformationByHandle(@file_handle, by_handle_file_information) return 0 end @@ -122,7 +138,7 @@ def delete_pending bufsize = 1024 buf = '\0' * bufsize - unless GetFileInformationByHandleEx.call(@file_handle, file_standard_info, buf, bufsize) + unless Win32API.GetFileInformationByHandleEx(@file_handle, file_standard_info, buf, bufsize) return false end diff --git a/lib/fluent/supervisor.rb b/lib/fluent/supervisor.rb index 854e53cb12..6f70ba885e 100644 --- a/lib/fluent/supervisor.rb +++ b/lib/fluent/supervisor.rb @@ -32,12 +32,6 @@ require 'serverengine' if Fluent.windows? - require 'windows/library' - require 'windows/synchronize' - require 'windows/system_info' - include Windows::Library - include Windows::Synchronize - include Windows::SystemInfo require 'win32/ipc' require 'win32/event' end @@ -235,7 +229,8 @@ def install_windows_event_handler end begin loop do - ipc_idx = ipc.wait_any(events.map {|e| e[:win32_event]}, Windows::Synchronize::INFINITE) + infinite = 0xFFFFFFFF + ipc_idx = ipc.wait_any(events.map {|e| e[:win32_event]}, infinite) event_idx = ipc_idx - 1 if event_idx >= 0 && event_idx < events.length diff --git a/lib/fluent/winsvc.rb b/lib/fluent/winsvc.rb index 8cfb807e43..d371922382 100644 --- a/lib/fluent/winsvc.rb +++ b/lib/fluent/winsvc.rb @@ -17,14 +17,10 @@ begin require 'optparse' - require 'windows/debug' - require 'Windows/Library' require 'win32/daemon' require 'win32/event' include Win32 - include Windows::Library - include Windows::Debug op = OptionParser.new opts = {service_name: nil} @@ -37,16 +33,14 @@ end def read_fluentdopt(service_name) - require 'win32/Registry' + require 'win32/registry' Win32::Registry::HKEY_LOCAL_MACHINE.open("SYSTEM\\CurrentControlSet\\Services\\#{service_name}") do |reg| reg.read("fluentdopt")[1] rescue "" end end def service_main_start(service_name) - ruby_path = 0.chr * 260 - GetModuleFileName.call(0, ruby_path,260) - ruby_path = ruby_path.rstrip.gsub(/\\/, '/') + ruby_path = ServerEngine.ruby_bin_path rubybin_dir = ruby_path[0, ruby_path.rindex("/")] opt = read_fluentdopt(service_name) Process.spawn("\"#{rubybin_dir}/ruby.exe\" \"#{rubybin_dir}/fluentd\" #{opt} -x #{service_name}") diff --git a/test/plugin/test_file_wrapper.rb b/test/plugin/test_file_wrapper.rb index 380cb4257c..93e7e61fbc 100644 --- a/test/plugin/test_file_wrapper.rb +++ b/test/plugin/test_file_wrapper.rb @@ -2,11 +2,6 @@ require 'fluent/plugin/file_wrapper' class FileWrapperTest < Test::Unit::TestCase - require 'windows/file' - require 'windows/error' - include Windows::File - include Windows::Error - TMP_DIR = File.dirname(__FILE__) + "/../tmp/file_wrapper#{ENV['TEST_ENV_NUMBER']}" def setup From f1f0bb2474ed8d4f7b6011a321a2b93e3b1dd9cb Mon Sep 17 00:00:00 2001 From: Takuro Ashie Date: Tue, 9 Aug 2022 11:31:48 +0900 Subject: [PATCH 2/2] Extract Win32 FFI code to lib/fluent/win32.rb Signed-off-by: Takuro Ashie --- lib/fluent/plugin/file_wrapper.rb | 21 ++--------------- lib/fluent/win32api.rb | 38 +++++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+), 19 deletions(-) create mode 100644 lib/fluent/win32api.rb diff --git a/lib/fluent/plugin/file_wrapper.rb b/lib/fluent/plugin/file_wrapper.rb index e99928b11a..91075a2aed 100644 --- a/lib/fluent/plugin/file_wrapper.rb +++ b/lib/fluent/plugin/file_wrapper.rb @@ -14,6 +14,8 @@ # limitations under the License. # +require 'fluent/win32api' + module Fluent module FileWrapper def self.open(path, mode='r') @@ -35,25 +37,6 @@ def self.stat(path) end end - module Win32API - require 'fiddle/import' - require 'fiddle/types' - extend Fiddle::Importer - - if RUBY_PLATFORM.split('-')[-1] == "ucrt" - MSVCRT_DLL = 'ucrtbase.dll' - else - MSVCRT_DLL = 'msvcrt.dll' - end - - dlload MSVCRT_DLL, "kernel32.dll" - include Fiddle::Win32Types - - extern "intptr_t _get_osfhandle(int)" - extern "BOOL GetFileInformationByHandle(HANDLE, void *)" - extern "BOOL GetFileInformationByHandleEx(HANDLE, int, void *, DWORD)" - end - class WindowsFile include File::Constants diff --git a/lib/fluent/win32api.rb b/lib/fluent/win32api.rb new file mode 100644 index 0000000000..d7757a8370 --- /dev/null +++ b/lib/fluent/win32api.rb @@ -0,0 +1,38 @@ +# +# Fluentd +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +require 'fluent/env' + +module Fluent + module Win32API + require 'fiddle/import' + require 'fiddle/types' + extend Fiddle::Importer + + if RUBY_PLATFORM.split('-')[-1] == "ucrt" + MSVCRT_DLL = 'ucrtbase.dll' + else + MSVCRT_DLL = 'msvcrt.dll' + end + + dlload MSVCRT_DLL, "kernel32.dll" + include Fiddle::Win32Types + + extern "intptr_t _get_osfhandle(int)" + extern "BOOL GetFileInformationByHandle(HANDLE, void *)" + extern "BOOL GetFileInformationByHandleEx(HANDLE, int, void *, DWORD)" + end if Fluent.windows? +end