]> source.dussan.org Git - redmine.git/commitdiff
Add timeout for thumbnail generation process (#37530).
authorGo MAEDA <maeda@farend.jp>
Mon, 27 May 2024 14:26:16 +0000 (14:26 +0000)
committerGo MAEDA <maeda@farend.jp>
Mon, 27 May 2024 14:26:16 +0000 (14:26 +0000)
Patch by Go MAEDA (@maeda).

git-svn-id: https://svn.redmine.org/redmine/trunk@22847 e93f8b46-1217-0410-a6f0-8f06a7374b81

config/configuration.yml.example
lib/redmine/configuration.rb
lib/redmine/thumbnail.rb
test/unit/attachment_test.rb

index ac127a4b5e43b9f06baba7c976cd33793cac322c..c528d764e07e9c45ad6ce161cad92a348b1c5123 100644 (file)
@@ -178,6 +178,10 @@ default:
   # the `gs` binary. Used to generate attachment thumbnails of PDF files.
   #gs_command:
 
+  # Timeout when generating thumbnails using the `convert` or `gs` command.
+  # Timeout is set in seconds.
+  #thumbnails_generation_timeout: 10
+
   # Configuration of MiniMagick font.
   #
   # Redmine uses MiniMagick in order to export a gantt chart to a PNG image.
index 00b76cbc178c0f4903264552eba2a69eaebfd3e8..4fdd29184083e94e2fb48b8e06e0355fd3205dfb 100644 (file)
@@ -27,7 +27,8 @@ module Redmine
       'avatar_server_url' => 'https://www.gravatar.com',
       'email_delivery' => nil,
       'max_concurrent_ajax_uploads' => 2,
-      'common_mark_enable_hardbreaks' => true
+      'common_mark_enable_hardbreaks' => true,
+      'thumbnails_generation_timeout' => 10
     }
 
     @config = nil
index 4c886a5b3ecc1c3606afc0119d32a667e75f0f6d..6a0729411f4cb94f2cf6b76de5b667f30baca518 100644 (file)
@@ -18,6 +18,7 @@
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 
 require 'fileutils'
+require 'timeout'
 
 module Redmine
   module Thumbnail
@@ -51,8 +52,20 @@ module Redmine
         else
           cmd = "#{shell_quote CONVERT_BIN} #{shell_quote source} -auto-orient -thumbnail #{shell_quote size_option} #{shell_quote target}"
         end
-        unless system(cmd)
-          logger.error("Creating thumbnail failed (#{$?}):\nCommand: #{cmd}")
+
+        pid = nil
+        begin
+          Timeout.timeout(Redmine::Configuration['thumbnails_generation_timeout'].to_i) do
+            pid = Process.spawn(cmd)
+            _, status = Process.wait2(pid)
+            unless status.success?
+              logger.error("Creating thumbnail failed (#{status.exitstatus}):\nCommand: #{cmd}")
+              return nil
+            end
+          end
+        rescue Timeout::Error
+          Process.kill('KILL', pid)
+          logger.error("Creating thumbnail timed out:\nCommand: #{cmd}")
           return nil
         end
       end
index 2e37672ab2bf59bb0d0c8c4627aa0a107bfb45b7..b88350fbac93b0544a8b57ea2933fa5ef797f4ff 100644 (file)
@@ -626,6 +626,25 @@ class AttachmentTest < ActiveSupport::TestCase
     ensure
       set_tmp_attachments_directory
     end
+
+    def test_thumbnail_should_timeout
+      dummy_pid = 37530
+      Process.stubs(:spawn).returns(dummy_pid)
+      Process.stubs(:wait2).raises(Timeout::Error)
+      Process.stubs(:kill).returns(1)
+      Process.stubs(:wait).returns(dummy_pid)
+      Rails.logger.expects(:error).with(regexp_matches(/Creating thumbnail timed out/))
+
+      set_fixtures_attachments_directory
+      Attachment.clear_thumbnails
+
+      attachment = Attachment.find(16)
+      thumbnail = attachment.thumbnail
+
+      assert_nil thumbnail
+    ensure
+      set_tmp_attachments_directory
+    end
   else
     puts '(ImageMagick convert not available)'
   end