what is a portable way in Ruby to check where STDIN will block if you attempt to read from it? -
i find out if there portable way check in ruby script whether block if attempts read stdin. following approach works unix (and cygwin) not native win32. (it based on perl approach learned long ago.)
$ cat read-stdin.rb
#! /usr/bin/ruby # test of reading stdin require 'fcntl' # trace info on input objects $stdout.sync=true if $debug # make sure standard output , error synchronized $stderr.print "argv=#{argv}\n" if $debug $stderr.print "argf=#{argf}\n" if $debug # see if input available, showing usage statement if not blocking_stdin = false if (defined? fcntl::f_getfl) $stderr.print "f_getfl=#{fcntl::f_getfl} o_rdwr=#{fcntl::o_rdwr}\n" if $debug flags = stdin.fcntl(fcntl::f_getfl, 0) $stderr.print "flags=#{flags}\n" if $debug blocking_stdin = true if ((flags & fcntl::o_rdwr) == fcntl::o_rdwr) $stderr.print "blocking_stdin=#{blocking_stdin}\n" if $debug end if (blocking_stdin && (argv.length == 0)) $stderr.print "usage: #{$0} [-]\n" process.exit end # read input , output $stderr.print "input:\n" if $debug input_text = argf.read() $stderr.print "output:\n" if $debug print "#{input_text}\n"
here interaction without debugging:
$ grep -v debug read-stdin.rb >| /tmp/simple-read-stdin.rb $ echo hey | ruby /tmp/simple-read-stdin.rb hey $ ruby /tmp/simple-read-stdin.rb usage: /tmp/simple-read-stdin.rb [-]
here interaction debugging:
$ echo hey | ruby -d read-stdin.rb argv= argf=argf f_getfl=3 o_rdwr=2 flags=65536 blocking_stdin=false input: output: hey $ ruby -d read-stdin.rb argv= argf=argf f_getfl=3 o_rdwr=2 flags=98306 blocking_stdin=true usage: read-stdin.rb [-]
i don't know if universally portable , don't know if considered idea (blocking isn't such bad concept) there non-blocking read method in io. can use this:
chunk = nil begin chunk = stdin.read_nonblock(4096) rescue errno::eagain # handle case if block chunk = 'nothing there...' end
though, think it's quite disappointing doesn't work without specifying buffer size io#read it, working around using loop should quite easy.
Comments
Post a Comment