Hi,

At Mon, 10 Jan 2005 23:05:17 +0900,
ts wrote in [ruby-core:04173]:
> n> Do you mean, in rb_dlsym_call(), the case that "to_ptr"
> n> conversion failed, and that copied strings for 's' arguments
> n> don't get freed?
> 
>  I've applied the patch
(snip)
> uln% ruby b.rb
> USER       PID %CPU %MEM   VSZ  RSS TTY      STAT START   TIME COMMAND
> ts       16531  0.0  0.0  9136 2408 pts/3    S    15:01   0:00 ruby b.rb
> ts       16531 23.0  0.0 14172 7460 pts/3    S    15:01   0:00 ruby b.rb
> ts       16531 45.0  0.1 18028 11316 pts/3   S    15:01   0:00 ruby b.rb
> ts       16531 66.0  0.1 22096 15384 pts/3   S    15:01   0:00 ruby b.rb
> ts       16531 87.0  0.2 25932 19220 pts/3   S    15:01   0:00 ruby b.rb
> ts       16531 99.9  0.2 29964 23252 pts/3   S    15:01   0:01 ruby b.rb
> ts       16531 64.5  0.3 33856 27144 pts/3   S    15:01   0:01 ruby b.rb
> ts       16531 75.5  0.3 37732 31020 pts/3   S    15:01   0:01 ruby b.rb
> ts       16531 86.5  0.4 41780 35068 pts/3   S    15:01   0:01 ruby b.rb
> ts       16531 97.0  0.4 45616 38904 pts/3   S    15:01   0:01 ruby b.rb
> ts       16531 71.6  0.5 49660 42948 pts/3   S    15:01   0:02 ruby b.rb
> ts       16531 79.0  0.5 53540 46828 pts/3   S    15:01   0:02 ruby b.rb
> ts       16531 86.0  0.6 57424 50712 pts/3   S    15:01   0:02 ruby b.rb
> ts       16531 93.3  0.6 61468 54756 pts/3   S    15:01   0:02 ruby b.rb
> ts       16531 75.5  0.7 65300 58588 pts/3   S    15:01   0:03 ruby b.rb
> ts       16531 81.0  0.7 69356 62644 pts/3   S    15:01   0:03 ruby b.rb
> ts       16531 86.5  0.8 73228 66516 pts/3   S    15:01   0:03 ruby b.rb
> ts       16531 92.0  0.8 77120 70408 pts/3   S    15:01   0:03 ruby b.rb
> ts       16531 97.5  0.9 81152 74440 pts/3   S    15:01   0:03 ruby b.rb
> ts       16531 82.4  0.9 84988 78276 pts/3   S    15:01   0:04 ruby b.rb
> ts       16531 86.8  1.0 89052 82340 pts/3   S    15:01   0:04 ruby b.rb
> ts       16531 91.2  1.0 92912 86200 pts/3   S    15:01   0:04 ruby b.rb
> ts       16531 95.4  1.1 96816 90104 pts/3   S    15:01   0:04 ruby b.rb
> ts       16531 83.1  1.1 100836 94124 pts/3  S    15:01   0:04 ruby b.rb
> ts       16531 86.8  1.2 104672 97960 pts/3  S    15:01   0:05 ruby b.rb

rb_dlsym_call() didn't free temporary argument lists.


Index: ext/dl/sym.c =================================================================== RCS file: /cvs/ruby/src/ruby/ext/dl/sym.c,v retrieving revision 1.27 diff -U2 -p -r1.27 sym.c --- ext/dl/sym.c 21 Dec 2004 23:34:43 -0000 1.27 +++ ext/dl/sym.c 10 Jan 2005 14:43:21 -0000 @@ -267,10 +267,9 @@ rb_dlsym_inspect(VALUE self) str_size = RSTRING(proto)->len + 100; - str = dlmalloc(str_size); - snprintf(str, str_size - 1, + val = rb_tainted_str_new(0, str_size); + snprintf(RSTRING(val)->ptr, str_size, "#<DL::Symbol:0x%p func=0x%p '%s'>", sym, sym->func, RSTRING(proto)->ptr); - val = rb_tainted_str_new2(str); - dlfree(str); + RSTRING(val)->len = strlen(RSTRING(val)->ptr); return val; @@ -467,5 +466,15 @@ rb_dlsym_call(int argc, VALUE argv[], VA dargs = ALLOC_N(ANY_TYPE, sym->len - 1); dtypes = ALLOC_N(int, sym->len - 1); -#define FREE_ARGS {xfree(args); xfree(dargs); xfree(dtypes);} +#define FREE_ARGS0 do {xfree(args); xfree(dargs); xfree(dtypes); } while (0) +#define FREE_ARGS_PARTIAL do { \ + do { \ + if( dtypes[i] == 's' && ANY2S(args[i]) ){ \ + dlfree((void *)ANY2S(args[i])); \ + ANY2S(args[i]) = 0; \ + } \ + } while (++i <= sym->len - 2); \ + FREE_ARGS0; \ + } while (0) +#define FREE_ARGS do {i = 0; FREE_ARGS_PARTIAL; } while (0) for( i = sym->len - 2; i >= 0; i-- ){ @@ -490,4 +499,5 @@ rb_dlsym_call(int argc, VALUE argv[], VA pval = rb_funcall(argv[i], rb_intern("to_ptr"), 0); if( !rb_obj_is_kind_of(pval, rb_cDLPtrData) ){ + FREE_ARGS_PARTIAL; rb_raise(rb_eDLTypeError, "unexpected type of argument #%d", i); } @@ -596,5 +606,5 @@ rb_dlsym_call(int argc, VALUE argv[], VA break; default: - FREE_ARGS; + FREE_ARGS_PARTIAL; rb_raise(rb_eDLTypeError, "unknown type '%c' of the return value.", @@ -923,9 +933,10 @@ rb_dlsym_call(int argc, VALUE argv[], VA }); dlfree((void*)ANY2S(args[i])); + ANY2S(args[i]) = 0; break; default: { char c = dtypes[i]; - FREE_ARGS; + FREE_ARGS_PARTIAL; rb_raise(rb_eRuntimeError, "unknown argument type '%c'", i, c); } @@ -942,5 +953,8 @@ rb_dlsym_call(int argc, VALUE argv[], VA } + FREE_ARGS0; #undef FREE_ARGS +#undef FREE_ARGS0 +#undef FREE_ARGS_PARTIAL return rb_assoc_new(val,dvals); }
-- Nobu Nakada