Project

General

Profile

Actions

Bug #2516

closed

IO#reopen Compatibility (original: [ruby-dev:39479])

Added by ujihisa (Tatsuhiro Ujihisa) over 14 years ago. Updated almost 13 years ago.

Status:
Rejected
Target version:
ruby -v:
ruby 1.9.2dev (2009-12-22 trunk 26152) [i386-darwin9.8.0]
Backport:

Description

=begin
takkanmさんとなかださんの[ruby-dev:39479]のスレッドによると、IO#reopenのnilの問題は解決したものの、いつのまにか挙動が変更されていたとのことです。
この変更は意図的なものなのか意図していないものなのかどちらなのでしょう。

 % cat test.rb
 f1 = File.open "file1.txt"
 f2 = File.open "file2.txt"
 f1.reopen f2
 puts f1.gets
 puts f1.gets
 puts(f1.reopen(f2).gets)
 % ruby -v
 ruby 1.8.7 (2009-06-12 patchlevel 174) [i686-darwin9]
 % ruby test.rb
 Line 1
 Line 2
 Line 1
 % ruby -v
 ruby 1.9.2dev (2009-10-17 trunk 25387) [i386-darwin9.8.0]
 % ruby test.rb
 Line 1
 Line 2
 Line 3

このissueは #1755 にも関連しています。
http://redmine.ruby-lang.org/issues/show/1755

意図したものならば、この変更をRubySpecにも反映させます。

個人的には現状の挙動が嬉しいです。

=end


Related issues 2 (0 open2 closed)

Related to Ruby master - Bug #2700: various behavior when reopening File twiceRejectednobu (Nobuyoshi Nakada)Actions
Related to Ruby master - Bug #2747: io.dup doesn't handle pos properlyRejected02/15/2010Actions
Actions #1

Updated by mame (Yusuke Endoh) about 14 years ago

=begin
遠藤です。

IO#reopen について調べているのですが、さっぱりわかりません。

$ cat foo.txt
1
2
3

1.8: 途中位置の File に reopen したら読み込めない

f1, f2 = File.new("foo.txt"), File.new("foo.txt")
f2.gets
f1.reopen(f2)
p f1.gets #=> nil
p f1.gets #=> nil
p f1.gets #=> nil
p f1.pos #=> 2

1.9: reopen した後は get 早い者勝ち? pos の結果が違う

f1, f2 = File.new("foo.txt"), File.new("foo.txt")
f1.reopen(f2)
p f1.gets #=> "1\n"
p f2.gets #=> nil
p f1.pos #=> 2
p f2.pos #=> 2

f1, f2 = File.new("foo.txt"), File.new("foo.txt")
f1.reopen(f2)
p f2.gets #=> "1\n"
p f1.gets #=> nil
p f1.pos #=> 6
p f2.pos #=> 2

reopen の想定ユースケースってどんなんでしょうか。
dup2 のようなものかと思っていたのですが、そんな挙動でもないですよね。
ユースケース次第では、reopen の引数に渡された IO は close してしまう
方が混乱しなくてすむと思います。

できればユースケースの議論の前に挙動が変わった理由を把握したかった

のですが、何がバグで何が仕様かわかりませんでした。

--
Yusuke Endoh
=end

Actions #2

Updated by kosaki (Motohiro KOSAKI) about 14 years ago

=begin
2010年2月11日15:24 Yusuke Endoh :

チケット [ruby-dev:39479]) (Rejected)" href="/issues/2516">#2516 が更新されました。 (by Yusuke Endoh)

遠藤です。

IO#reopen について調べているのですが、さっぱりわかりません。

 $ cat foo.txt
 1
 2
 3

 # 1.8: 途中位置の File に reopen したら読み込めない
 f1, f2 = File.new("foo.txt"), File.new("foo.txt")
 f2.gets
 f1.reopen(f2)
 p f1.gets #=> nil
 p f1.gets #=> nil
 p f1.gets #=> nil
 p f1.pos  #=> 2

 # 1.9: reopen した後は get 早い者勝ち? pos の結果が違う
 f1, f2 = File.new("foo.txt"), File.new("foo.txt")
 f1.reopen(f2)
 p f1.gets #=> "1\n"
 p f2.gets #=> nil
 p f1.pos  #=> 2
 p f2.pos  #=> 2

 f1, f2 = File.new("foo.txt"), File.new("foo.txt")
 f1.reopen(f2)
 p f2.gets #=> "1\n"
 p f1.gets #=> nil
 p f1.pos  #=> 6
 p f2.pos  #=> 2

reopen の想定ユースケースってどんなんでしょうか。
dup2 のようなものかと思っていたのですが、そんな挙動でもないですよね。
ユースケース次第では、reopen の引数に渡された IO は close してしまう
方が混乱しなくてすむと思います。

できればユースケースの議論の前に挙動が変わった理由を把握したかった

のですが、何がバグで何が仕様かわかりませんでした。

Linuxだと同等の以下のCプログラムが

#include <stdio.h>

int main(void)
{
FILE *f1, *f2;
char buf[80];

     f1 = fopen("inputfile", "r+");
     printf("%s", fgets(buf, 80, f1));
     f2 = freopen("inputfile", "r+", f1);

     printf("%s", fgets(buf, 80, f1));
     printf("%s", fgets(buf, 80, f1));
     printf("%s", fgets(buf, 80, f1));

     printf("pos %d\n", ftell(f1));
     printf("pos %d\n", ftell(f2));

}

こうなります。

1
1
2
3
pos 6
pos 6

内部的には struct FILEが struct _IO_marker をポイントしていて、 _IO_markerは共有、そっちでpos管理している。

また SUSをみると

http://www.opengroup.org/onlinepubs/009695399/functions/freopen.html

最初に引数streamをflushしてcloseするよん。とか書いてあるけど、Linuxは単にdupしてるだけなんでcloseしてないみたい。なんか互換性の理由があるのかな?

IO系は見るからに標準Cライブラリの影響が色濃いので、これに合わせればいいんじゃないでしょうかねぇ・・・
nalshさんあたりが悲鳴を上げる恐れがありますが。

=end

Actions #3

Updated by mame (Yusuke Endoh) about 14 years ago

=begin
遠藤です。

2010年2月15日13:25 KOSAKI Motohiro :

反応がないので、誰も興味がないのだと判断します。遠藤さんとIRCで調整のうえ
kosakiがボールを握ることにしました。
現状 io.dup もposが狂った動きをしているので一緒に直すことになると思います。

IO とか興味ないのでよろしくお願いします。

あと、IRC で話した pos のとち狂った動きについて記録です。

○ pos が負になる

$ cat foo.txt
1
2
3

f1 = File.new("foo.txt")
f2 = File.new("foo.txt")
f2.gets
f1.reopen(f2)
f2.gets
f1.rewind
p f2.pos #=> -2

○ pos に副作用がある

f1 = File.new("foo.txt")
f2 = File.new("foo.txt")
f2.gets
f1.reopen(f2)
f2.gets
p f1.pos #=> 6
p f2.pos #=> 4
p f1.pos #=> 4

--
Yusuke ENDOH

=end

Actions #4

Updated by mame (Yusuke Endoh) almost 14 years ago

  • Status changed from Assigned to Rejected

=begin
遠藤です。

1.9.2 では仕様ということで reject します。([ruby-core:28335] 他)

わかりにくい挙動なことは確かなので、1.9.3 以降での改善を Feature
チケットとして別に登録しておきます。

--
Yusuke Endoh
=end

Actions

Also available in: Atom PDF

Like0
Like0Like0Like0Like0