From fcafcd5708be21e4615e73f9ff879ac803d15331 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oliver=20G=C3=BCnther?= Date: Thu, 23 Aug 2018 15:14:39 +0200 Subject: [PATCH] Use posix-spawn to spawn childprocess with timeout of 10 (configurable) seconds --- Gemfile | 3 +++ Gemfile.lock | 2 ++ .../formats/markdown/pandoc_wrapper.rb | 18 ++++++++++++------ .../formats/markdown/textile_converter.rb | 10 ++++++++-- 4 files changed, 25 insertions(+), 8 deletions(-) diff --git a/Gemfile b/Gemfile index 4329b96537c..5d8f28f2932 100644 --- a/Gemfile +++ b/Gemfile @@ -95,6 +95,9 @@ gem 'ruby-duration', '~> 3.2.0' # provide compatible filesystem information for available storage gem 'sys-filesystem', '~> 1.1.4', require: false +# Faster posix-compliant spawns for 8.0. conversions with pandoc +gem 'posix-spawn', '~> 0.3.13', require: false + gem 'bcrypt', '~> 3.1.6' gem 'multi_json', '~> 1.12.1' diff --git a/Gemfile.lock b/Gemfile.lock index 6a254a7579d..4f3e4fbd44e 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -384,6 +384,7 @@ GEM activesupport (> 2.2.1) nokogiri (~> 1.8.1) rubyzip (~> 1.2.1) + posix-spawn (0.3.13) powerpack (0.1.1) prawn (2.2.2) pdf-core (~> 0.7.0) @@ -680,6 +681,7 @@ DEPENDENCIES passenger (~> 5.3.3) pg (~> 1.0.0) plaintext (= 0.1.0) + posix-spawn (~> 0.3.13) prawn (~> 2.2) prawn-table (~> 0.2.2) pry-byebug (~> 3.6.0) diff --git a/lib/open_project/text_formatting/formats/markdown/pandoc_wrapper.rb b/lib/open_project/text_formatting/formats/markdown/pandoc_wrapper.rb index 388935624a5..798f7bbc56a 100644 --- a/lib/open_project/text_formatting/formats/markdown/pandoc_wrapper.rb +++ b/lib/open_project/text_formatting/formats/markdown/pandoc_wrapper.rb @@ -28,7 +28,7 @@ # See docs/COPYRIGHT.rdoc for more details. #++ -require 'open3' +require 'posix-spawn' module OpenProject::TextFormatting::Formats module Markdown @@ -97,18 +97,24 @@ module OpenProject::TextFormatting::Formats private ## - # Run pandoc through open3 and raise if an exception occurred - def run_pandoc!(args, **options) - output, stderr_str, status = Open3.capture3('pandoc', *args, **options) - raise stderr_str unless status.success? + # Run pandoc through posix-spawn and raise if an exception occurred + def run_pandoc!(command, stdin_data: nil, timeout: pandoc_timeout) + child = POSIX::Spawn::Child.new('pandoc', *command, input: stdin_data, timeout: timeout) + raise child.err unless child.status.success? - output + child.out + rescue POSIX::Spawn::TimeoutExceeded => e + raise Timeout::Error, "Timeout occurred while running pandoc: #{e.message}" end def read_usage_string run_pandoc! %w[--help] end + def pandoc_timeout + ENV.fetch('OPENPROJECT_PANDOC_TIMEOUT_SECONDS', 10).to_i + end + def read_output_formats @output_formats ||= begin begin diff --git a/lib/open_project/text_formatting/formats/markdown/textile_converter.rb b/lib/open_project/text_formatting/formats/markdown/textile_converter.rb index 6f91a06c828..7a181e72453 100644 --- a/lib/open_project/text_formatting/formats/markdown/textile_converter.rb +++ b/lib/open_project/text_formatting/formats/markdown/textile_converter.rb @@ -117,7 +117,6 @@ module OpenProject::TextFormatting::Formats # Iterate in batches to avoid plucking too much with_original_values_in_batches(klass, attributes) do |orig_values| markdowns_in_groups = bulk_convert_textile_with_fallback(orig_values, attributes) - new_values = new_values_for(attributes, orig_values, markdowns_in_groups) next if new_values.empty? @@ -198,11 +197,18 @@ module OpenProject::TextFormatting::Formats markdown = execute_pandoc_with_stdin! textile - cleanup_after_pandoc(markdown) + if markdown.empty? + markdown + else + cleanup_after_pandoc(markdown) + end end def execute_pandoc_with_stdin!(textile) pandoc.execute! textile + rescue Timeout::Error => e + warn "Execution of pandoc failed: #{e}" + '' rescue StandardError => e raise "Execution of pandoc failed: #{e}" end