Skip to content

Commit

Permalink
Merge pull request #2649 from fluent/fix-child_process-stderr
Browse files Browse the repository at this point in the history
child_process helper: fix stderr blocking for discard case. fix #2609
  • Loading branch information
repeatedly authored Oct 15, 2019
2 parents a7894c4 + 3077226 commit 48ed651
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 2 deletions.
5 changes: 3 additions & 2 deletions lib/fluent/plugin_helper/child_process.rb
Original file line number Diff line number Diff line change
Expand Up @@ -257,7 +257,8 @@ def child_process_execute_once(
readio = writeio = stderrio = wait_thread = nil
readio_in_use = writeio_in_use = stderrio_in_use = false

if !mode.include?(:stderr) && !mode.include?(:read_with_stderr) && stderr != :discard # connect
if !mode.include?(:stderr) && !mode.include?(:read_with_stderr)
spawn_opts[:err] = IO::NULL if stderr == :discard
writeio, readio, wait_thread = *Open3.popen2(*spawn_args, spawn_opts)
elsif mode.include?(:read_with_stderr)
writeio, readio, wait_thread = *Open3.popen2e(*spawn_args, spawn_opts)
Expand All @@ -281,7 +282,7 @@ def child_process_execute_once(
stderrio.set_encoding(external_encoding, internal_encoding, encoding_options)
stderrio_in_use = true
else
stderrio.reopen(IO::NULL) if stderrio && stderrio == :discard
stderrio.reopen(IO::NULL) if stderrio && stderr == :discard
end

pid = wait_thread.pid # wait_thread => Process::Waiter
Expand Down
37 changes: 37 additions & 0 deletions test/plugin_helper/test_child_process.rb
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,43 @@ def configure(conf)
assert_equal expected, ary
end

test 'can execute external command at just once, which can handle both of read and write. Ignore stderr message/no block' do
m = Mutex.new
ary = []
Timeout.timeout(TEST_DEADLOCK_TIMEOUT) do
ran = false
# lots of stderr message should not be blocked and message should not be printed in test.
cmd = "ruby -e 'while !STDIN.eof? && line = STDIN.readline; STDERR.puts line.chomp * 1000; STDOUT.puts line.chomp; STDOUT.flush rescue nil; end'"
@d.child_process_execute(:t2_and_ignore_stderr, cmd, mode: [:write, :read]) do |writeio, readio|
m.lock
ran = true

[[1,2],[3,4],[5,6]].each do |i,j|
writeio.write "my data#{i}\n"
writeio.write "my data#{j}\n"
writeio.flush
end
writeio.close

while line = readio.readline
ary << line
end
m.unlock
end
begin
sleep TEST_WAIT_INTERVAL_FOR_BLOCK_RUNNING until m.locked? || ran
m.lock
rescue
ensure
m.unlock
end
end

assert_equal [], @d.log.out.logs
expected = (1..6).map{|i| "my data#{i}\n" }
assert_equal expected, ary
end

test 'can execute external command at just once, which can handle all of read, write and stderr' do
m = Mutex.new
ary1 = []
Expand Down

0 comments on commit 48ed651

Please sign in to comment.