-
Notifications
You must be signed in to change notification settings - Fork 58
Add support for streaming stdout/stderr from Child invocations #75
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from 2 commits
9206712
0c02f33
b6e35f8
254704a
25dc138
54647e6
f263cfc
ac327f0
4bf5d80
90acd30
c83a7ef
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||
|---|---|---|---|---|
|
|
@@ -95,6 +95,13 @@ def initialize(*args) | |||
| @options[:pgroup] = true | ||||
| end | ||||
| @options.delete(:chdir) if @options[:chdir].nil? | ||||
| @streaming = false | ||||
| if streams = @options.delete(:streams) | ||||
| @stdout_block = streams[:stdout] | ||||
| @stderr_block = streams[:stderr] | ||||
|
|
||||
| @streaming = !!@stdout_block || !!@stderr_block | ||||
| end | ||||
| exec! if !@options.delete(:noexec) | ||||
| end | ||||
|
|
||||
|
|
@@ -244,14 +251,35 @@ def read_and_write(input, stdin, stdout, stderr, timeout=nil, max=nil) | |||
|
|
||||
| # read from stdout and stderr streams | ||||
| ready[0].each do |fd| | ||||
| buf = (fd == stdout) ? @out : @err | ||||
| chunk = nil | ||||
| begin | ||||
| buf << fd.readpartial(BUFSIZE) | ||||
| chunk = fd.readpartial(BUFSIZE) | ||||
|
||||
| rescue Errno::EAGAIN, Errno::EINTR | ||||
| rescue EOFError | ||||
| readers.delete(fd) | ||||
| fd.close | ||||
| end | ||||
|
|
||||
| abort = false | ||||
| if chunk | ||||
| if fd == stdout | ||||
| if @streaming && @stdout_block | ||||
| abort = !!@stdout_block.call(chunk) | ||||
| else | ||||
| @out << chunk | ||||
| end | ||||
|
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I decided to just drop returning these in an attempt at consistency since these one or both of these ivars are useless if we're streaming. |
||||
| else | ||||
| if @streaming && @stderr_block | ||||
| abort = !!@stderr_block.call(chunk) | ||||
| else | ||||
| @err << chunk | ||||
| end | ||||
| end | ||||
| end | ||||
|
||||
|
|
||||
| if @streaming && abort | ||||
|
||||
| raise Aborted | ||||
|
||||
| rescue Object |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -224,6 +224,65 @@ def test_utf8_input_long | |
| assert p.success? | ||
| end | ||
|
|
||
| def test_streaming_stdout | ||
| stdout_buf = "" | ||
| stdout_stream = Proc.new do |chunk| | ||
| stdout_buf << chunk | ||
|
|
||
| false | ||
| end | ||
|
|
||
| input = "hello!" | ||
| p = Child.new('cat', :input => input, :streams => { | ||
| :stdout => stdout_stream | ||
| }) | ||
|
|
||
| assert p.success? | ||
| assert_equal input, stdout_buf | ||
| end | ||
|
|
||
| def test_streaming_stderr | ||
| stderr_buf = "" | ||
| stderr_stream = Proc.new do |chunk| | ||
| stderr_buf << chunk | ||
|
|
||
| false | ||
| end | ||
|
|
||
| p = Child.new('ls', '-?', :streams => { | ||
| :stderr => stderr_stream | ||
| }) | ||
|
|
||
| refute p.success? | ||
| refute stderr_buf.empty? | ||
| end | ||
|
|
||
| def test_streaming_stdout_aborted | ||
| stdout_stream = Proc.new do |chunk| | ||
| true | ||
| end | ||
|
|
||
| input = "hello!" | ||
| assert_raises POSIX::Spawn::Aborted do | ||
| p = Child.new('cat', :input => input, :streams => { | ||
| :stdout => stdout_stream | ||
| }) | ||
| end | ||
| end | ||
|
|
||
| def test_streaming_stderr_aborted | ||
| stderr_stream = Proc.new do |chunk| | ||
| true | ||
| end | ||
|
|
||
| input = "hello!" | ||
| assert_raises POSIX::Spawn::Aborted do | ||
| p = Child.new('ls', '-?', :streams => { | ||
| :stderr => stderr_stream | ||
| }) | ||
| end | ||
| end | ||
|
|
||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There are no tests that involve reading more than one There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
| ## | ||
| # Assertion Helpers | ||
|
|
||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This could maybe be
CallerAbortedor something more specific?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm fine with either.