ext/dl/ptr.c:26:
static void
rb_dlmem_delete(void *ptr)
{
rb_secure(4);
rb_hash_delete(DLMemoryTable, DLLONG2NUM(ptr));
}
Eventually ptr crosses the boundary of fixnum, causing a bignum to be
created. It appears to be an error to create a non-immediate VALUE
while inside a free() function (memory corruption or segfault).
Here's my attempted fix. Note that I change the keys of
DLMemoryTable. From what I could decipher from the Japanese
documentation, it doesn't appear that DLMemoryTable is part of the
API.
There was also a memory leak in dlptr_free().
Index: ext/dl/dl.h
===================================================================
RCS file: /src/ruby/ext/dl/dl.h,v
retrieving revision 1.9
diff -u -r1.9 dl.h
--- ext/dl/dl.h 1 Dec 2003 23:02:44 -0000 1.9
+++ ext/dl/dl.h 19 May 2004 06:38:03 -0000
@@ -210,6 +210,9 @@
# define DLNUM2LONG(x) (long)(NUM2INT(x))
#endif
+#define DLPTR2FIX(x) LONG2FIX(((unsigned long)(x)) >> 1)
+#define DLFIX2PTR(x) ((void*)(FIX2ULONG(x) << 1))
+
typedef struct { char c; void *x; } s_voidp;
typedef struct { char c; short x; } s_short;
typedef struct { char c; int x; } s_int;
Index: ext/dl/ptr.c
===================================================================
RCS file: /src/ruby/ext/dl/ptr.c,v
retrieving revision 1.19
diff -u -r1.19 ptr.c
--- ext/dl/ptr.c 22 Oct 2003 14:29:20 -0000 1.19
+++ ext/dl/ptr.c 19 May 2004 06:38:03 -0000
@@ -9,6 +9,8 @@
VALUE rb_cDLPtrData;
VALUE rb_mDLMemorySpace;
+
+/* keys are shifted pointers to fit into fixnums */
static VALUE DLMemoryTable;
#ifndef T_SYMBOL
@@ -27,7 +29,7 @@
rb_dlmem_delete(void *ptr)
{
rb_secure(4);
- rb_hash_delete(DLMemoryTable, DLLONG2NUM(ptr));
+ rb_hash_delete(DLMemoryTable, DLPTR2FIX(ptr));
}
static void
@@ -37,7 +39,7 @@
rb_dlmem_delete(ptr);
}
else{
- rb_hash_aset(DLMemoryTable, DLLONG2NUM(ptr), DLLONG2NUM(obj));
+ rb_hash_aset(DLMemoryTable, DLPTR2FIX(ptr), DLLONG2NUM(obj));
}
}
@@ -46,7 +48,7 @@
{
VALUE val;
- val = rb_hash_aref(DLMemoryTable, DLLONG2NUM(ptr));
+ val = rb_hash_aref(DLMemoryTable, DLPTR2FIX(ptr));
return val == Qnil ? Qnil : (VALUE)DLNUM2LONG(val);
}
@@ -69,6 +71,7 @@
if (data->stype) dlfree(data->stype);
if (data->ssize) dlfree(data->ssize);
if (data->ids) dlfree(data->ids);
+ free(data);
}
void
@@ -1013,7 +1016,7 @@
VALUE key, val;
key = rb_ary_entry(assoc, 0);
val = rb_ary_entry(assoc, 1);
- rb_yield(rb_assoc_new(key,(VALUE)DLNUM2LONG(val)));
+ rb_yield(rb_assoc_new(ULONG2NUM(FIX2PTR(key)),(VALUE)DLNUM2LONG(val)));
return Qnil;
}
__________________________________
Do you Yahoo!?
SBC Yahoo! - Internet access at a great low price.
http://promo.yahoo.com/sbc/