[#30549] [ANN] Ruby 1.8.6 has been released — "Akinori MUSHA" <knu@...>

 Ruby 1.8.6 をリリースしました。

14 messages 2007/03/12

[#30553] help: lib/shell for ruby 1.9 — keiju@... (Keiju ISHITSUKA)

けいじゅ@いしつかです.

13 messages 2007/03/13
[#30585] Re: help: lib/shell for ruby 1.9 — Yukihiro Matsumoto <matz@...> 2007/03/15

まつもと ゆきひろです

[#30587] Re: help: lib/shell for ruby 1.9 — keiju@... (石塚圭樹) 2007/03/15

けいじゅ@いしつかです.

[#30588] Re: help: lib/shell for ruby 1.9 — Yukihiro Matsumoto <matz@...> 2007/03/15

まつもと ゆきひろです

[ruby-dev:30620] DL.callback as free function causes errors

From: sheepman <sheepman@...>
Date: 2007-03-18 01:43:11 UTC
List: ruby-dev #30620
こんにちは、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


Attachments (1)

dl.pacth.txt (3 KB, text/x-diff)
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);


In This Thread

Prev Next