From: sheepman Date: 2007-03-18T10:43:11+09:00 Subject: [ruby-dev:30620] DL.callback as free function causes errors This is a multi-part message in MIME format. --Multipart=_Sun__18_Mar_2007_10_43_14_+0900_NFw1BTUN20Beuf9j Content-Type: text/plain; charset=ISO-2022-JP Content-Transfer-Encoding: 7bit こんにちは、sheepman です。 DL::PtrData オブジェクトでは ruby が GC をする時に呼ぶ free function を指定することができます。 で、たとえば regex ライブラリだと regfree したあとに、 free を呼びたいので、以下のような DL.callback を使ったコードを 書きたくなります。 require 'dl' include DL h = dlopen(nil) regcomp = h.sym('regcomp', 'IPSI') regfree = h.sym('regfree', '0P') free = callback('0P'){|ptr| regfree[ptr] FREE[ptr] } 100000.times do |i| ptr = PtrData.malloc(50, free) regcomp.call(ptr, '123', 0) end しかし、これは segv します。原因を正確に追うことができていないのですが、 おそらく GC の真最中にブロックが呼ばれることで起きているんだと思います。 というわけで、DL::Symbol オブジェクトにcallbackかどうかのフラグを持たせて、 callback は PtrData の free 関数として指定できないようにパッチを書いてみました。 segv している原因が違っているなら、このパッチは無用のものになります。 -- sheepman / TAMURA Takashi sheepman@sheepman.sakura.ne.jp --Multipart=_Sun__18_Mar_2007_10_43_14_+0900_NFw1BTUN20Beuf9j Content-Type: text/plain; name="dl.pacth.txt" Content-Disposition: attachment; filename="dl.pacth.txt" Content-Transfer-Encoding: 7bit Index: dl.c =================================================================== --- dl.c (revision 12087) +++ dl.c (working copy) @@ -653,7 +653,7 @@ rb_assoc_new(INT2NUM(rettype),INT2NUM(entry)), rb_assoc_new(type,proc)); sprintf(fname, "rb_dl_callback_func_%d_%d", rettype, entry); - return rb_dlsym_new((void (*)())rb_dl_callback_table[rettype][entry], + return rb_dlsym_callback_new((void (*)())rb_dl_callback_table[rettype][entry], fname, RSTRING(type)->ptr); } Index: dl.h =================================================================== --- dl.h (revision 12087) +++ dl.h (working copy) @@ -261,6 +261,7 @@ char *name; char *type; int len; + int is_callback; }; enum DLPTR_CTYPE { Index: ptr.c =================================================================== --- ptr.c (revision 12087) +++ ptr.c (working copy) @@ -128,6 +128,15 @@ return rb_dlptr_new2(rb_cDLPtrData, ptr, size, func); } +static +void +dlptr_check_free_func(VALUE sym) +{ + if(rb_dlsym_is_callback(sym) == Qtrue){ + rb_raise(rb_eDLTypeError, "free function must not be callbak defined by DL.callback"); + } +} + VALUE rb_dlptr_malloc(long size, freefunc_t func) { @@ -200,6 +209,7 @@ case 3: p = (void*)(DLNUM2LONG(rb_Integer(ptr))); s = DLNUM2LONG(size); + dlptr_check_free_func(sym); f = rb_dlsym2csym(sym); break; default: @@ -233,6 +243,7 @@ break; case 2: s = NUM2INT(size); + dlptr_check_free_func(sym); f = rb_dlsym2csym(sym); break; default: @@ -285,6 +296,8 @@ { struct ptr_data *data; + dlptr_check_free_func(val); + Data_Get_Struct(self, struct ptr_data, data); data->free = DLFREEFUNC(rb_dlsym2csym(val)); Index: sym.c =================================================================== --- sym.c (revision 12087) +++ sym.c (working copy) @@ -108,6 +108,17 @@ return val; } +VALUE +rb_dlsym_callback_new(void (*func)(), const char *name, const char *type) +{ + VALUE val; + struct sym_data *data; + val = rb_dlsym_new(func, name, type); + Data_Get_Struct(val, struct sym_data, data); + data->is_callback = 1; + return val; +} + freefunc_t rb_dlsym2csym(VALUE val) { @@ -139,7 +150,8 @@ data->name = 0; data->type = 0; data->len = 0; - + data->is_callback = 0; + return obj; } @@ -185,6 +197,14 @@ } VALUE +rb_dlsym_is_callback(VALUE self) +{ + struct sym_data *sym; + Data_Get_Struct(self, struct sym_data, sym); + return sym->is_callback ? Qtrue : Qfalse; +} + +VALUE rb_dlsym_name(VALUE self) { struct sym_data *sym; @@ -974,6 +994,7 @@ rb_define_method(rb_cDLSymbol, "call", rb_dlsym_call, -1); rb_define_method(rb_cDLSymbol, "[]", rb_dlsym_call, -1); rb_define_method(rb_cDLSymbol, "name", rb_dlsym_name, 0); + rb_define_method(rb_cDLSymbol, "is_callback?", rb_dlsym_is_callback, 0); rb_define_method(rb_cDLSymbol, "proto", rb_dlsym_proto, 0); rb_define_method(rb_cDLSymbol, "cproto", rb_dlsym_cproto, 0); rb_define_method(rb_cDLSymbol, "inspect", rb_dlsym_inspect, 0); --Multipart=_Sun__18_Mar_2007_10_43_14_+0900_NFw1BTUN20Beuf9j--