[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

これはどういったことが起きているのでしょうか?

In This Thread

Prev Next