Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.ruby > #7338 > unrolled thread

How to flush stdin to popen3 without closing it?

Started byPetter Gustad <newsmailcomp6@gustad.com>
First post2017-02-26 17:36 +0100
Last post2017-02-26 22:53 +0100
Articles 4 — 2 participants

Back to article view | Back to comp.lang.ruby


Contents

  How to flush stdin to popen3 without closing it? Petter Gustad <newsmailcomp6@gustad.com> - 2017-02-26 17:36 +0100
    Re: How to flush stdin to popen3 without closing it? Robert Klemme <shortcutter@googlemail.com> - 2017-02-26 18:42 +0100
      Re: How to flush stdin to popen3 without closing it? Petter Gustad <newsmailcomp6@gustad.com> - 2017-02-26 22:46 +0100
        Re: How to flush stdin to popen3 without closing it? Robert Klemme <shortcutter@googlemail.com> - 2017-02-26 22:53 +0100

#7338 — How to flush stdin to popen3 without closing it?

FromPetter Gustad <newsmailcomp6@gustad.com>
Date2017-02-26 17:36 +0100
SubjectHow to flush stdin to popen3 without closing it?
Message-ID<8760jwkiyv.fsf@filestore.home.gustad.com>
It seems like stdin must be closed for popen3 to send stdin to the
sub-process. How can I do something like this:

   require 'open3'
   
   stdin, stdout, stderr, wait_thr = Open3.popen3("dc")
   stdin.puts "1 2 + p"
   stdin.flush # does not not help
   stdin.close # without this it will just hang on the read
   res = stdout.read
   puts "1+2 is #{res}"
   #stdin.reopen # is it possible to re-open the stdin somehow?
   stdin.puts "#{res} 2 * p"
   stdin.close
   res = stdout.read
   puts "(1+2)*2 is #{res}"
   ...

Is there a way to flush or re-open stdin? Is there some other variation
of popen3 which can be used?

Thanks!

//Petter

-- 
.sig removed by request. 

[toc] | [next] | [standalone]


#7339

FromRobert Klemme <shortcutter@googlemail.com>
Date2017-02-26 18:42 +0100
Message-ID<ehgid3F3dm4U1@mid.individual.net>
In reply to#7338
On 26.02.2017 17:36, Petter Gustad wrote:
>
> It seems like stdin must be closed for popen3 to send stdin to the
> sub-process. How can I do something like this:
>
>    require 'open3'
>
>    stdin, stdout, stderr, wait_thr = Open3.popen3("dc")
>    stdin.puts "1 2 + p"
>    stdin.flush # does not not help
>    stdin.close # without this it will just hang on the read
>    res = stdout.read
>    puts "1+2 is #{res}"
>    #stdin.reopen # is it possible to re-open the stdin somehow?
>    stdin.puts "#{res} 2 * p"
>    stdin.close
>    res = stdout.read
>    puts "(1+2)*2 is #{res}"
>    ...
>
> Is there a way to flush or re-open stdin? Is there some other variation
> of popen3 which can be used?

You are missing one important point: stdout.read must block until dc 
closes its output because there is no limit set on the read amount.  And 
that will only happen if dc's input has been closed because, obviously, 
dc needs to be able to write results as long as input is coming.  If you 
replace that line with

res = stdout.gets

it will work the way you expect.  You could also use stdout.sync=true to 
avoid to have to use #flush all the time.

http://ruby-doc.org/core-2.4.0/IO.html#method-i-sync-3D

Kind regards

	robert

-- 
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/

[toc] | [prev] | [next] | [standalone]


#7340

FromPetter Gustad <newsmailcomp6@gustad.com>
Date2017-02-26 22:46 +0100
Message-ID<87h93gd3s7.fsf@filestore.home.gustad.com>
In reply to#7339
Robert Klemme <shortcutter@googlemail.com> writes:

> On 26.02.2017 17:36, Petter Gustad wrote:
>>
>> It seems like stdin must be closed for popen3 to send stdin to the
>> sub-process. How can I do something like this:
>>
>>    require 'open3'
>>
>>    stdin, stdout, stderr, wait_thr = Open3.popen3("dc")
>>    stdin.puts "1 2 + p"
>>    stdin.flush # does not not help
>>    stdin.close # without this it will just hang on the read
>>    res = stdout.read
>>    puts "1+2 is #{res}"
>>    #stdin.reopen # is it possible to re-open the stdin somehow?
>>    stdin.puts "#{res} 2 * p"
>>    stdin.close
>>    res = stdout.read
>>    puts "(1+2)*2 is #{res}"
>>    ...
>>
>> Is there a way to flush or re-open stdin? Is there some other variation
>> of popen3 which can be used?
>
> You are missing one important point: stdout.read must block until dc
> closes its output because there is no limit set on the read amount.
> And that will only happen if dc's input has been closed because,
> obviously, dc needs to be able to write results as long as input is
> coming.  If you replace that line with
>
> res = stdout.gets
>
> it will work the way you expect.  You could also use stdout.sync=true
> to avoid to have to use #flush all the time.
>
> http://ruby-doc.org/core-2.4.0/IO.html#method-i-sync-3D

Thanks! Actually I was thinking readline, where I was writing read, and
of course the correct ruby method is gets...

require 'open3'

stdin, stdout, stderr, wait_thr = Open3.popen3("dc")
stdin.puts "1 2 + p"
res = stdout.gets
puts "1+2 is #{res}"
stdin.puts "#{res} 2 * p"
res = stdout.gets
puts "(1+2)*2 is #{res}"

The above results in:

1+2 is 3
(1+2)*2 is 6

Again, thanks!

Best regards
//Petter

-- 
.sig removed by request. 

[toc] | [prev] | [next] | [standalone]


#7341

FromRobert Klemme <shortcutter@googlemail.com>
Date2017-02-26 22:53 +0100
Message-ID<ehh12jF6dltU1@mid.individual.net>
In reply to#7340
On 26.02.2017 22:46, Petter Gustad wrote:

> Again, thanks!

You're welcome!  Just one more caveat, which might not apply in this 
case but a general advice for #popen and the likes: buffers between 
processes are limited.  If you handle everything single threaded there 
is potential for deadlock.  This will always happen if you send more 
data longer than the buffer size to the pipe and the other process will 
also send more than buffer size data.  Then both are blocked on IO.

Kind regards

	robert


-- 
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/

[toc] | [prev] | [standalone]


Back to top | Article view | comp.lang.ruby


csiph-web