• How to flush stdin to popen3 without closing it?

    From Petter Gustad@21:1/5 to All on Sun Feb 26 17:36:08 2017
    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.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Robert Klemme@21:1/5 to Petter Gustad on Sun Feb 26 18:42:58 2017
    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/

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Robert Klemme@21:1/5 to Petter Gustad on Sun Feb 26 22:53:21 2017
    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/

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Petter Gustad@21:1/5 to Robert Klemme on Sun Feb 26 22:46:00 2017
    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.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)