Defect #44378 » 0002-Fix-the-gs-process-surviving-when-PDF-thumbnail-gene.patch
| lib/redmine/thumbnail.rb | ||
|---|---|---|
| 58 | 58 |
pid = nil |
| 59 | 59 |
begin |
| 60 | 60 |
Timeout.timeout(Redmine::Configuration['thumbnails_generation_timeout'].to_i) do |
| 61 |
pid = Process.spawn(cmd) |
|
| 61 |
# Run the command in its own process group so that the whole |
|
| 62 |
# process tree (eg. the gs process spawned by convert for PDF |
|
| 63 |
# files) can be killed on timeout. Process groups are not |
|
| 64 |
# available on Windows. |
|
| 65 |
spawn_options = Redmine::Platform.mswin? ? {} : {:pgroup => true}
|
|
| 66 |
pid = Process.spawn(cmd, spawn_options) |
|
| 62 | 67 |
_, status = Process.wait2(pid) |
| 63 | 68 |
unless status.success? |
| 64 | 69 |
logger.error("Creating thumbnail failed (#{status.exitstatus}):\nCommand: #{cmd}")
|
| ... | ... | |
| 67 | 72 |
end |
| 68 | 73 |
rescue Timeout::Error |
| 69 | 74 |
if pid |
| 70 |
Process.kill('KILL', pid)
|
|
| 75 |
begin |
|
| 76 |
# A negative pid sends the signal to the whole process group |
|
| 77 |
Process.kill('KILL', Redmine::Platform.mswin? ? pid : -pid)
|
|
| 78 |
rescue Errno::ESRCH |
|
| 79 |
# The process is already gone |
|
| 80 |
end |
|
| 71 | 81 |
Process.detach(pid) |
| 72 | 82 |
end |
| 73 | 83 |
logger.error("Creating thumbnail timed out:\nCommand: #{cmd}")
|
| test/unit/attachment_test.rb | ||
|---|---|---|
| 787 | 787 |
set_tmp_attachments_directory |
| 788 | 788 |
end |
| 789 |
def test_thumbnail_should_timeout |
|
| 789 |
def test_thumbnail_should_kill_and_detach_process_group_on_timeout
|
|
| 790 | 790 |
dummy_pid = 37530 |
| 791 |
Process.stubs(:spawn).returns(dummy_pid) |
|
| 792 |
Process.stubs(:wait2).raises(Timeout::Error) |
|
| 793 |
Process.stubs(:kill).returns(1) |
|
| 794 |
Process.stubs(:wait).returns(dummy_pid) |
|
| 791 | ||
| 792 |
Redmine::Platform.stubs(:mswin?).returns(false) |
|
| 793 |
Redmine::Thumbnail.stubs(:gs_available?).returns(true) |
|
| 794 |
Process.expects(:spawn). |
|
| 795 |
with(anything, {:pgroup => true}).
|
|
| 796 |
returns(dummy_pid) |
|
| 797 |
Process.expects(:wait2). |
|
| 798 |
with(dummy_pid). |
|
| 799 |
raises(Timeout::Error) |
|
| 800 |
# A negative pid sends the signal to the whole process group so that |
|
| 801 |
# child processes of convert (eg. gs) are killed as well |
|
| 802 |
Process.expects(:kill). |
|
| 803 |
with('KILL', -dummy_pid).
|
|
| 804 |
returns(1) |
|
| 805 |
Process.expects(:detach). |
|
| 806 |
with(dummy_pid) |
|
| 795 | 807 |
Rails.logger.expects(:error).with(regexp_matches(/Creating thumbnail timed out/)) |
| 796 | 808 |
set_fixtures_attachments_directory |
| 797 | 809 |
Attachment.clear_thumbnails |
| 798 |
attachment = Attachment.find(16) |
|
| 810 |
# Use a PDF attachment because convert spawns a Ghostscript (gs) |
|
| 811 |
# child process for PDFs, which must not survive the timeout |
|
| 812 |
attachment = Attachment.find(23) |
|
| 799 | 813 |
thumbnail = attachment.thumbnail |
| 800 | 814 |
assert_nil thumbnail |
| 801 | 815 |
ensure |
| 802 | 816 |
set_tmp_attachments_directory |
| 803 | 817 |
end |
| 818 | ||
| 804 | 819 |
else |
| 805 | 820 |
puts '(ImageMagick convert not available)' |
| 806 | 821 |
end |
- « Previous
- 1
- 2
- Next »