#2009 File.open memory leak

e$B$H$_$?$G$9!#e(B

e$B1Q8l$O%@%a$J$N$Ge(B ruby-dev e$B$G!De(B

http://redmine.ruby-lang.org/issues/show/2009 e$B$Ne(B File.open memory
leak
e$B$G$9$,!"860x$Oe(B r21435 e$B$Ne(B gc.c e$B$N<!$NJQ99$@$H;W$$$^$9!#e(B

@@ -1274,8 +1291,11 @@
break;
case T_FILE:
if (RANY(obj)->as.file.fptr) {

  •  rb_io_fptr_finalize(RANY(obj)->as.file.fptr);
    
  •  RUBY_CRITICAL(free(RANY(obj)->as.file.fptr));
    
  •  struct rb_io_t *fptr = RANY(obj)->as.file.fptr;
    
  •  make_deferred(RANY(obj));
    
  •  RDATA(obj)->dfree = (void (*)(void*))rb_io_fptr_finalize;
    
  •  RDATA(obj)->data = fptr;
    
  •  return 1;
    
    }
    break;
    case T_ICLASS:

fptr e$B$Ne(B free() e$B$,$J$/$J$C$?$?$a$K%a%b%j%j!<%/$7$F$^$9!#e(B

e$B<!$N$h$&$J$9$l$PD>$j$^$7$?!#e(B

Index: gc.c

— gc.c (e$B%j%S%8%g%se(B 25170)
+++ gc.c (e$B:n6H%3%T!<e(B)
@@ -1243,6 +1243,14 @@
p->as.basic.flags = (p->as.basic.flags & ~T_MASK) | T_DEFERRED;
}

+static void
+fptr_finalize_and_free(fptr)

  • void *fptr;
    +{
  • rb_io_fptr_finalize(fptr);
  • free(fptr);
    +}

static int
obj_free(obj)
VALUE obj;
@@ -1318,7 +1326,7 @@
if (RANY(obj)->as.file.fptr) {
struct rb_io_t *fptr = RANY(obj)->as.file.fptr;
make_deferred(RANY(obj));

  •  RDATA(obj)->dfree = (void (*)(void*))rb_io_fptr_finalize;
    
  •  RDATA(obj)->dfree = (void (*)(void*))fptr_finalize_and_free;
     RDATA(obj)->data = fptr;
     return 1;
    
    }

e$B$^$D$b$He(B e$B$f$-$R$m$G$9e(B

In message “Re: [ruby-dev:39410] #2009 File.open memory leak”
on Wed, 30 Sep 2009 23:54:20 +0900, e$B$H$_$?$^$5$R$me(B
[email protected] writes:

|# e$B1Q8l$O%@%a$J$N$Ge(B ruby-dev e$B$G!De(B
|
|http://redmine.ruby-lang.org/issues/show/2009 e$B$Ne(B File.open memory leak
|e$B$G$9$,!"860x$Oe(B r21435 e$B$Ne(B gc.c e$B$N<!$NJQ99$@$H;W$$$^$9!#e(B

e$B$J$k$[$I!#e(B

|fptr e$B$Ne(B free() e$B$,$J$/$J$C$?$?$a$K%a%b%j%j!<%/$7$F$^$9!#e(B
|
|e$B<!$N$h$&$J$9$l$PD>$j$^$7$?!#e(B

1.9e$B$N$h$&$Ke(Brb_io_fptr_finalize()e$B$N:G8e$Ge(Bfptre$B$re(Bxfree()e$B$9$l$PNIe(B
e$B$$$h$&$K;W$$$^$9!#e(B

e$B$3$s$J%Q%C%A$r=q$$$F$_$^$7$?!#e(Bmake teste$B$/$i$$$O$A$c$s$HF0$/e(B
e$B$h$&$G$9!#:NMQ$9$k$+$I$&$+$Oe(B1.8e$B$N%a%s%F%J!<$KG$$;$^$9!#e(B

— a/io.c
+++ b/io.c
@@ -2348,10 +2348,10 @@ rb_io_fptr_finalize(fptr)
if (fptr->path) {
free(fptr->path);
}

  • if (!fptr->f && !fptr->f2) return;
  • if (fileno(fptr->f) < 3) return;
  • rb_io_fptr_cleanup(fptr, Qtrue);
  • if ((fptr->f && fileno(fptr->f) > 2) || fptr->f2) {
  • rb_io_fptr_cleanup(fptr, Qtrue);
  • }
  • xfree(fptr);
    }

VALUE

At Thu, 1 Oct 2009 01:18:34 +0900,
matz wrote:

|fptr の free() がなくなったためにメモリリークしてます。
|
|次のようなすれば直りました。

1.9のようにrb_io_fptr_finalize()の最後でfptrをxfree()すれば良
いように思います。

こんなパッチを書いてみました。make testくらいはちゃんと動く
ようです。採用するかどうかは1.8のメンテナーに任せます。

1.9でも rb_io_fptr_finalize() が free(fptr) しているのでこれが
いいと思います。commitをお願いします。