[Groonga-commit] ranguba/chupa-text at ebf8a6d [master] external-command: add support for soft limit

Back to archive index
Kouhei Sutou null+****@clear*****
Thu Mar 28 12:40:09 JST 2019


Kouhei Sutou	2019-03-28 12:40:09 +0900 (Thu, 28 Mar 2019)

  Revision: ebf8a6d9bcdc8038ad877f280b789b07189a3ac4
  https://github.com/ranguba/chupa-text/commit/ebf8a6d9bcdc8038ad877f280b789b07189a3ac4

  Message:
    external-command: add support for soft limit

  Modified files:
    lib/chupa-text/external-command.rb
    test/test-external-command.rb

  Modified: lib/chupa-text/external-command.rb (+40 -3)
===================================================================
--- lib/chupa-text/external-command.rb    2019-03-28 12:22:17 +0900 (7d50eb0)
+++ lib/chupa-text/external-command.rb    2019-03-28 12:40:09 +0900 (2a2d524)
@@ -25,7 +25,9 @@ module ChupaText
     @default_timeout = nil
     @default_soft_timeout = nil
     @default_limit_cpu = nil
+    @default_soft_limit_cpu = nil
     @default_limit_as = nil
+    @default_soft_limit_as = nil
     class << self
       def default_timeout
         @default_timeout || ENV["CHUPA_TEXT_EXTERNAL_COMMAND_TIMEOUT"]
@@ -51,6 +53,14 @@ module ChupaText
         @default_limit_cpu = cpu
       end
 
+      def default_soft_limit_cpu
+        @default_soft_limit_cpu
+      end
+
+      def default_soft_limit_cpu=(cpu)
+        @default_soft_limit_cpu = cpu
+      end
+
       def default_limit_as
         @default_limit_as || limit_env("AS")
       end
@@ -59,6 +69,14 @@ module ChupaText
         @default_limit_as = as
       end
 
+      def default_soft_limit_as
+        @default_soft_limit_as
+      end
+
+      def default_soft_limit_as=(as)
+        @default_soft_limit_as = as
+      end
+
       private
       def limit_env(name)
         ENV["CHUPA_TEXT_EXTERNAL_COMMAND_LIMIT_#{name}"] ||
@@ -110,7 +128,7 @@ module ChupaText
     private
     def spawn_options(user_options)
       options = (user_options || {}).dup
-      apply_default_spawn_limit(options, :cpu, :int)
+      apply_default_spawn_limit(options, :cpu, :time)
       apply_default_spawn_limit(options, :as, :size)
       options
     end
@@ -120,16 +138,26 @@ module ChupaText
       case key
       when :cpu
         option_key = :rlimit_cpu
+        unit = "s"
       when :as
         option_key = :rlimit_as
+        unit = ""
       else
         option_key = :"rlimit_#{key}"
+        unit = ""
       end
       return if options[option_key]
 
       tag = "[limit][#{key}]"
       value = self.class.__send__("default_limit_#{key}")
       value = __send__("parse_#{type}", tag, value)
+      soft_value = self.class.__send__("default_soft_limit_#{key}")
+      soft_value = __send__("parse_#{type}", tag, soft_value)
+      if value
+        value = soft_value if soft_value and soft_value < value
+      else
+        value = soft_value
+      end
       return if value.nil?
       rlimit_number = Process.const_get("RLIMIT_#{key.to_s.upcase}")
       soft_limit, hard_limit = Process.getrlimit(rlimit_number)
@@ -138,7 +166,7 @@ module ChupaText
         return nil
       end
       limit_info = "soft-limit:#{soft_limit}, hard-limit:#{hard_limit}"
-      info("#{log_tag}#{tag}[set] <#{value}>(#{limit_info})")
+      info("#{log_tag}#{tag}[set] <#{value}#{unit}>(#{limit_info})")
 
       options[option_key] = value
     end
@@ -178,12 +206,21 @@ module ChupaText
         scale = 1
         case value
         when /GB?\z/i
+          scale = 1000 ** 3
+          number = $PREMATCH
+        when /GiB?\z/i
           scale = 1024 ** 3
           number = $PREMATCH
         when /MB?\z/i
+          scale = 1000 ** 2
+          number = $PREMATCH
+        when /MiB?\z/i
           scale = 1024 ** 2
           number = $PREMATCH
-        when /KB?\z/i
+        when /[kK]B?\z/i
+          scale = 1000 ** 1
+          number = $PREMATCH
+        when /KiB?\z/i
           scale = 1024 ** 1
           number = $PREMATCH
         when /B?\z/i

  Modified: test/test-external-command.rb (+174 -0)
===================================================================
--- test/test-external-command.rb    2019-03-28 12:22:17 +0900 (a07cd40)
+++ test/test-external-command.rb    2019-03-28 12:40:09 +0900 (54d69a7)
@@ -215,4 +215,178 @@ class TestExternalCommand < Test::Unit::TestCase
                    messages)
     end
   end
+
+  class TestLimitCPU < self
+    def setup
+      limit_cpu = ChupaText::ExternalCommand.default_limit_cpu
+      soft_limit_cpu = ChupaText::ExternalCommand.default_soft_limit_cpu
+      begin
+        yield
+      ensure
+        ChupaText::ExternalCommand.default_limit_cpu = limit_cpu
+        ChupaText::ExternalCommand.default_soft_limit_cpu = soft_limit_cpu
+      end
+    end
+
+    def run_command(spawn_options={})
+      command = create_command(ruby)
+      command.run("-e", "true",
+                  spawn_options: spawn_options)
+    end
+
+    def test_default
+      ChupaText::ExternalCommand.default_limit_cpu = "60s"
+      messages = capture_log do
+        run_command
+      end
+      soft_limit, hard_limit = Process.getrlimit(Process::RLIMIT_CPU)
+      assert_equal([
+                     [
+                       :info,
+                       "[external-command][limit][cpu][set] <60.0s>" +
+                       "(soft-limit:#{soft_limit}, hard-limit:#{hard_limit})",
+                     ]
+                   ],
+                   messages)
+    end
+
+    def test_default_soft_not_use
+      ChupaText::ExternalCommand.default_limit_cpu = "60s"
+      ChupaText::ExternalCommand.default_soft_limit_cpu = "90s"
+      messages = capture_log do
+        run_command
+      end
+      soft_limit, hard_limit = Process.getrlimit(Process::RLIMIT_CPU)
+      assert_equal([
+                     [
+                       :info,
+                       "[external-command][limit][cpu][set] <60.0s>" +
+                       "(soft-limit:#{soft_limit}, hard-limit:#{hard_limit})",
+                     ]
+                   ],
+                   messages)
+    end
+
+    def test_default_soft_use
+      ChupaText::ExternalCommand.default_limit_cpu = "60s"
+      ChupaText::ExternalCommand.default_soft_limit_cpu = "30s"
+      messages = capture_log do
+        run_command
+      end
+      soft_limit, hard_limit = Process.getrlimit(Process::RLIMIT_CPU)
+      assert_equal([
+                     [
+                       :info,
+                       "[external-command][limit][cpu][set] <30.0s>" +
+                       "(soft-limit:#{soft_limit}, hard-limit:#{hard_limit})",
+                     ]
+                   ],
+                   messages)
+    end
+
+    def test_default_soft_only
+      ChupaText::ExternalCommand.default_soft_limit_cpu = "30s"
+      messages = capture_log do
+        run_command
+      end
+      soft_limit, hard_limit = Process.getrlimit(Process::RLIMIT_CPU)
+      assert_equal([
+                     [
+                       :info,
+                       "[external-command][limit][cpu][set] <30.0s>" +
+                       "(soft-limit:#{soft_limit}, hard-limit:#{hard_limit})",
+                     ]
+                   ],
+                   messages)
+    end
+  end
+
+  class TestLimitAS < self
+    def setup
+      limit_as = ChupaText::ExternalCommand.default_limit_as
+      soft_limit_as = ChupaText::ExternalCommand.default_soft_limit_as
+      begin
+        yield
+      ensure
+        ChupaText::ExternalCommand.default_limit_as = limit_as
+        ChupaText::ExternalCommand.default_soft_limit_as = soft_limit_as
+      end
+    end
+
+    def run_command(spawn_options={})
+      command = create_command(ruby)
+      command.run("-e", "true",
+                  spawn_options: spawn_options)
+    end
+
+    def test_default
+      ChupaText::ExternalCommand.default_limit_as = "100MiB"
+      messages = capture_log do
+        run_command
+      end
+      soft_limit, hard_limit = Process.getrlimit(Process::RLIMIT_AS)
+      assert_equal([
+                     [
+                       :info,
+                       "[external-command][limit][as][set] " +
+                       "<#{100 * 1024 * 1024}>" +
+                       "(soft-limit:#{soft_limit}, hard-limit:#{hard_limit})",
+                     ]
+                   ],
+                   messages)
+    end
+
+    def test_default_soft_not_use
+      ChupaText::ExternalCommand.default_limit_as = "100MiB"
+      ChupaText::ExternalCommand.default_soft_limit_as = "150MiB"
+      messages = capture_log do
+        run_command
+      end
+      soft_limit, hard_limit = Process.getrlimit(Process::RLIMIT_AS)
+      assert_equal([
+                     [
+                       :info,
+                       "[external-command][limit][as][set] " +
+                       "<#{100 * 1024 * 1024}>" +
+                       "(soft-limit:#{soft_limit}, hard-limit:#{hard_limit})",
+                     ]
+                   ],
+                   messages)
+    end
+
+    def test_default_soft_use
+      ChupaText::ExternalCommand.default_limit_as = "100MiB"
+      ChupaText::ExternalCommand.default_soft_limit_as = "50MiB"
+      messages = capture_log do
+        run_command
+      end
+      soft_limit, hard_limit = Process.getrlimit(Process::RLIMIT_AS)
+      assert_equal([
+                     [
+                       :info,
+                       "[external-command][limit][as][set] " +
+                       "<#{50 * 1024 * 1024}>" +
+                       "(soft-limit:#{soft_limit}, hard-limit:#{hard_limit})",
+                     ]
+                   ],
+                   messages)
+    end
+
+    def test_default_soft_only
+      ChupaText::ExternalCommand.default_soft_limit_as = "50MiB"
+      messages = capture_log do
+        run_command
+      end
+      soft_limit, hard_limit = Process.getrlimit(Process::RLIMIT_AS)
+      assert_equal([
+                     [
+                       :info,
+                       "[external-command][limit][as][set] " +
+                       "<#{50 * 1024 * 1024}>" +
+                       "(soft-limit:#{soft_limit}, hard-limit:#{hard_limit})",
+                     ]
+                   ],
+                   messages)
+    end
+  end
 end
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.osdn.me/mailman/archives/groonga-commit/attachments/20190328/4609574f/attachment-0001.html>


More information about the Groonga-commit mailing list
Back to archive index