[ruby-list:50818] Rubyとファイルディスクリプタの継承について
From:
MASAKI Haruka <yek@...>
Date:
2019-09-12 13:29:45 UTC
List:
ruby-list #50818
正木です。
Rubyにおいて状況によって子プロセスにファイルディスクリプタが引き継がれていなかったり、
EOFに達した状態で引き渡されたりしている、
ということなのですが、perl及びpythonでも同様の状況を確認しているため、Ruby固有ではないかもしれません。
しかし、調べてみてもどうにも自己解決に至らなかったのでご助力お願いします。
次の例では子プロセスのcatにファイルディスクリプタが引き渡され、catから一行読めています。
% ruby -e 'IO.popen(["cat"], "r") {|io| puts "#{io.gets} GET" }' -e 'p STDIN.eof?' -e 'puts STDIN.read' < 5LINES
AAA
GET
true
しかし、事前にIO#eof?すると、catにはファイルディスクリプタが引き継がれていません。
% ruby -e 'p STDIN.eof?' -e 'IO.popen(["cat"], "r") {|io| puts "#{io.gets} GET" }' -e 'p STDIN.eof?' -e 'puts STDIN.read' < 5LINES
false
GET
false
AAA
BBB
CCC
DDD
EEE
FFF
次の例ではrubyは一行読んでいるだけですが、EOFまで進んでしまいます。
% print -l A B C D E | ( ruby -e 'gets' && cat )
これはファイルから読んでも同じです。
% ( ruby -e 'gets' && cat ) < file
ところが、IO#posするとcatには2行目以降が渡るようになります。
% ( ruby -e 'gets' -e 'STDIN.pos' && cat ) < file
B
C
D
E
execした場合も同様で普通はからっぽですが
% ( ruby -e 'gets' -e 'exec("cat")' ) < file
IO#posするとcatに渡ります。
% ( ruby -e 'gets' -e 'STDIN.pos' -e 'exec("cat")' ) < file
B
C
D
E
これはどういったことが起きているのでしょうか?