Use exclusive lock in :ruby filter

The :ruby filter redirects $stdout, which causes problems in multi-
threaded environments.

Wrap code generated by :ruby filter in `Thread.exclusive` block.

Also use ensure block to make sure $stdout is reset correctly if an
exception is raised.
This commit is contained in:
Matt Wildig 2012-12-14 09:59:20 +00:00
parent 3d7b799d7e
commit 68977f3368
1 changed files with 12 additions and 4 deletions

View File

@ -263,6 +263,9 @@ RUBY
# available if the {file:REFERENCE.md#suppress_eval-option `:suppress_eval`}
# option is set to true. The Ruby code is evaluated in the same context as
# the Haml template.
#
# The code in the filter has an exclusive lock (using `Thread.exlusive`) when
# it runs, to prevent issues from sharing the global `$stdout`.
module Ruby
include Base
require 'stringio'
@ -272,11 +275,16 @@ RUBY
return if compiler.options[:suppress_eval]
compiler.instance_eval do
push_silent <<-FIRST.gsub("\n", ';') + text + <<-LAST.gsub("\n", ';')
_haml_old_stdout = $stdout
$stdout = StringIO.new(_hamlout.buffer, 'a')
Thread.exclusive do
begin
_haml_old_stdout = $stdout
$stdout = StringIO.new(_hamlout.buffer, 'a')
FIRST
_haml_old_stdout, $stdout = $stdout, _haml_old_stdout
_haml_old_stdout.close
ensure
_haml_old_stdout, $stdout = $stdout, _haml_old_stdout
_haml_old_stdout.close
end
end
LAST
end
end