* ext/dl/cfunc.c (dlcfunc_mark), ext/dl/cptr.c (dlptr_mark):
workaround to mark wrapped object. this is not a true fix, because [Bug #4929] is caused by the interface design of DL. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@32712 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
5c815b733d
commit
9f3914aba6
@ -1,3 +1,9 @@
|
|||||||
|
Thu Jul 28 02:15:04 2011 Nobuyoshi Nakada <nobu@ruby-lang.org>
|
||||||
|
|
||||||
|
* ext/dl/cfunc.c (dlcfunc_mark), ext/dl/cptr.c (dlptr_mark):
|
||||||
|
workaround to mark wrapped object. this is not a true fix,
|
||||||
|
because [Bug #4929] is caused by the interface design of DL.
|
||||||
|
|
||||||
Thu Jul 28 00:28:15 2011 NARUSE, Yui <naruse@ruby-lang.org>
|
Thu Jul 28 00:28:15 2011 NARUSE, Yui <naruse@ruby-lang.org>
|
||||||
|
|
||||||
* test/fileutils/test_fileutils.rb: add OpenBSD case.
|
* test/fileutils/test_fileutils.rb: add OpenBSD case.
|
||||||
|
@ -41,6 +41,14 @@ rb_dl_set_win32_last_error(VALUE self, VALUE val)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static void
|
||||||
|
dlcfunc_mark(void *ptr)
|
||||||
|
{
|
||||||
|
struct cfunc_data *data = ptr;
|
||||||
|
if (data->wrap) {
|
||||||
|
rb_gc_mark(data->wrap);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
dlcfunc_free(void *ptr)
|
dlcfunc_free(void *ptr)
|
||||||
@ -68,7 +76,7 @@ dlcfunc_memsize(const void *ptr)
|
|||||||
|
|
||||||
const rb_data_type_t dlcfunc_data_type = {
|
const rb_data_type_t dlcfunc_data_type = {
|
||||||
"dl/cfunc",
|
"dl/cfunc",
|
||||||
{0, dlcfunc_free, dlcfunc_memsize,},
|
{dlcfunc_mark, dlcfunc_free, dlcfunc_memsize,},
|
||||||
};
|
};
|
||||||
|
|
||||||
VALUE
|
VALUE
|
||||||
@ -143,14 +151,15 @@ rb_dlcfunc_kind_p(VALUE func)
|
|||||||
static VALUE
|
static VALUE
|
||||||
rb_dlcfunc_initialize(int argc, VALUE argv[], VALUE self)
|
rb_dlcfunc_initialize(int argc, VALUE argv[], VALUE self)
|
||||||
{
|
{
|
||||||
VALUE addr, name, type, calltype;
|
VALUE addr, name, type, calltype, addrnum;
|
||||||
struct cfunc_data *data;
|
struct cfunc_data *data;
|
||||||
void *saddr;
|
void *saddr;
|
||||||
const char *sname;
|
const char *sname;
|
||||||
|
|
||||||
rb_scan_args(argc, argv, "13", &addr, &type, &name, &calltype);
|
rb_scan_args(argc, argv, "13", &addr, &type, &name, &calltype);
|
||||||
|
|
||||||
saddr = (void*)(NUM2PTR(rb_Integer(addr)));
|
addrnum = rb_Integer(addr);
|
||||||
|
saddr = (void*)(NUM2PTR(addrnum));
|
||||||
sname = NIL_P(name) ? NULL : StringValuePtr(name);
|
sname = NIL_P(name) ? NULL : StringValuePtr(name);
|
||||||
|
|
||||||
TypedData_Get_Struct(self, struct cfunc_data, &dlcfunc_data_type, data);
|
TypedData_Get_Struct(self, struct cfunc_data, &dlcfunc_data_type, data);
|
||||||
@ -159,6 +168,7 @@ rb_dlcfunc_initialize(int argc, VALUE argv[], VALUE self)
|
|||||||
data->name = sname ? strdup(sname) : 0;
|
data->name = sname ? strdup(sname) : 0;
|
||||||
data->type = NIL_P(type) ? DLTYPE_VOID : NUM2INT(type);
|
data->type = NIL_P(type) ? DLTYPE_VOID : NUM2INT(type);
|
||||||
data->calltype = NIL_P(calltype) ? CFUNC_CDECL : SYM2ID(calltype);
|
data->calltype = NIL_P(calltype) ? CFUNC_CDECL : SYM2ID(calltype);
|
||||||
|
data->wrap = (addrnum == addr) ? 0 : addr;
|
||||||
|
|
||||||
return Qnil;
|
return Qnil;
|
||||||
}
|
}
|
||||||
|
@ -10,19 +10,36 @@
|
|||||||
VALUE rb_cDLCPtr;
|
VALUE rb_cDLCPtr;
|
||||||
|
|
||||||
static inline freefunc_t
|
static inline freefunc_t
|
||||||
get_freefunc(VALUE func)
|
get_freefunc(VALUE func, volatile VALUE *wrap)
|
||||||
{
|
{
|
||||||
|
VALUE addrnum;
|
||||||
if (NIL_P(func)) {
|
if (NIL_P(func)) {
|
||||||
|
*wrap = 0;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
if (rb_dlcfunc_kind_p(func)) {
|
if (rb_dlcfunc_kind_p(func)) {
|
||||||
|
*wrap = func;
|
||||||
return (freefunc_t)(VALUE)RCFUNC_DATA(func)->ptr;
|
return (freefunc_t)(VALUE)RCFUNC_DATA(func)->ptr;
|
||||||
}
|
}
|
||||||
return (freefunc_t)(VALUE)NUM2PTR(rb_Integer(func));
|
addrnum = rb_Integer(func);
|
||||||
|
*wrap = (addrnum != func) ? func : 0;
|
||||||
|
return (freefunc_t)(VALUE)NUM2PTR(addrnum);
|
||||||
}
|
}
|
||||||
|
|
||||||
static ID id_to_ptr;
|
static ID id_to_ptr;
|
||||||
|
|
||||||
|
static void
|
||||||
|
dlptr_mark(void *ptr)
|
||||||
|
{
|
||||||
|
struct ptr_data *data = ptr;
|
||||||
|
if (data->wrap[0]) {
|
||||||
|
rb_gc_mark(data->wrap[0]);
|
||||||
|
}
|
||||||
|
if (data->wrap[1]) {
|
||||||
|
rb_gc_mark(data->wrap[1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
dlptr_free(void *ptr)
|
dlptr_free(void *ptr)
|
||||||
{
|
{
|
||||||
@ -43,7 +60,7 @@ dlptr_memsize(const void *ptr)
|
|||||||
|
|
||||||
static const rb_data_type_t dlptr_data_type = {
|
static const rb_data_type_t dlptr_data_type = {
|
||||||
"dl/ptr",
|
"dl/ptr",
|
||||||
{0, dlptr_free, dlptr_memsize,},
|
{dlptr_mark, dlptr_free, dlptr_memsize,},
|
||||||
};
|
};
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -135,27 +152,22 @@ rb_dlptr_s_allocate(VALUE klass)
|
|||||||
static VALUE
|
static VALUE
|
||||||
rb_dlptr_initialize(int argc, VALUE argv[], VALUE self)
|
rb_dlptr_initialize(int argc, VALUE argv[], VALUE self)
|
||||||
{
|
{
|
||||||
VALUE ptr, sym, size;
|
VALUE ptr, sym, size, wrap = 0, funcwrap = 0;
|
||||||
struct ptr_data *data;
|
struct ptr_data *data;
|
||||||
void *p = NULL;
|
void *p = NULL;
|
||||||
freefunc_t f = NULL;
|
freefunc_t f = NULL;
|
||||||
long s = 0;
|
long s = 0;
|
||||||
|
|
||||||
switch (rb_scan_args(argc, argv, "12", &ptr, &size, &sym)) {
|
if (rb_scan_args(argc, argv, "12", &ptr, &size, &sym) >= 1) {
|
||||||
case 1:
|
VALUE addrnum = rb_Integer(ptr);
|
||||||
p = (void*)(NUM2PTR(rb_Integer(ptr)));
|
if (addrnum != ptr) wrap = ptr;
|
||||||
break;
|
p = NUM2PTR(addrnum);
|
||||||
case 2:
|
}
|
||||||
p = (void*)(NUM2PTR(rb_Integer(ptr)));
|
if (argc >= 2) {
|
||||||
s = NUM2LONG(size);
|
s = NUM2LONG(size);
|
||||||
break;
|
}
|
||||||
case 3:
|
if (argc >= 3) {
|
||||||
p = (void*)(NUM2PTR(rb_Integer(ptr)));
|
f = get_freefunc(sym, &funcwrap);
|
||||||
s = NUM2LONG(size);
|
|
||||||
f = get_freefunc(sym);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
rb_bug("rb_dlptr_initialize");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (p) {
|
if (p) {
|
||||||
@ -164,6 +176,8 @@ rb_dlptr_initialize(int argc, VALUE argv[], VALUE self)
|
|||||||
/* Free previous memory. Use of inappropriate initialize may cause SEGV. */
|
/* Free previous memory. Use of inappropriate initialize may cause SEGV. */
|
||||||
(*(data->free))(data->ptr);
|
(*(data->free))(data->ptr);
|
||||||
}
|
}
|
||||||
|
data->wrap[0] = wrap;
|
||||||
|
data->wrap[1] = funcwrap;
|
||||||
data->ptr = p;
|
data->ptr = p;
|
||||||
data->size = s;
|
data->size = s;
|
||||||
data->free = f;
|
data->free = f;
|
||||||
@ -185,7 +199,7 @@ rb_dlptr_initialize(int argc, VALUE argv[], VALUE self)
|
|||||||
static VALUE
|
static VALUE
|
||||||
rb_dlptr_s_malloc(int argc, VALUE argv[], VALUE klass)
|
rb_dlptr_s_malloc(int argc, VALUE argv[], VALUE klass)
|
||||||
{
|
{
|
||||||
VALUE size, sym, obj;
|
VALUE size, sym, obj, wrap = 0;
|
||||||
long s;
|
long s;
|
||||||
freefunc_t f;
|
freefunc_t f;
|
||||||
|
|
||||||
@ -196,13 +210,14 @@ rb_dlptr_s_malloc(int argc, VALUE argv[], VALUE klass)
|
|||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
s = NUM2LONG(size);
|
s = NUM2LONG(size);
|
||||||
f = get_freefunc(sym);
|
f = get_freefunc(sym, &wrap);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
rb_bug("rb_dlptr_s_malloc");
|
rb_bug("rb_dlptr_s_malloc");
|
||||||
}
|
}
|
||||||
|
|
||||||
obj = rb_dlptr_malloc(s,f);
|
obj = rb_dlptr_malloc(s,f);
|
||||||
|
if (wrap) RPTR_DATA(obj)->wrap[1] = wrap;
|
||||||
|
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
@ -289,7 +304,7 @@ rb_dlptr_free_set(VALUE self, VALUE val)
|
|||||||
struct ptr_data *data;
|
struct ptr_data *data;
|
||||||
|
|
||||||
TypedData_Get_Struct(self, struct ptr_data, &dlptr_data_type, data);
|
TypedData_Get_Struct(self, struct ptr_data, &dlptr_data_type, data);
|
||||||
data->free = get_freefunc(val);
|
data->free = get_freefunc(val, &data->wrap[1]);
|
||||||
|
|
||||||
return Qnil;
|
return Qnil;
|
||||||
}
|
}
|
||||||
@ -582,7 +597,7 @@ rb_dlptr_size_get(VALUE self)
|
|||||||
static VALUE
|
static VALUE
|
||||||
rb_dlptr_s_to_ptr(VALUE self, VALUE val)
|
rb_dlptr_s_to_ptr(VALUE self, VALUE val)
|
||||||
{
|
{
|
||||||
VALUE ptr;
|
VALUE ptr, wrap = val;
|
||||||
|
|
||||||
if (RTEST(rb_obj_is_kind_of(val, rb_cIO))){
|
if (RTEST(rb_obj_is_kind_of(val, rb_cIO))){
|
||||||
rb_io_t *fptr;
|
rb_io_t *fptr;
|
||||||
@ -599,16 +614,19 @@ rb_dlptr_s_to_ptr(VALUE self, VALUE val)
|
|||||||
VALUE vptr = rb_funcall(val, id_to_ptr, 0);
|
VALUE vptr = rb_funcall(val, id_to_ptr, 0);
|
||||||
if (rb_obj_is_kind_of(vptr, rb_cDLCPtr)){
|
if (rb_obj_is_kind_of(vptr, rb_cDLCPtr)){
|
||||||
ptr = vptr;
|
ptr = vptr;
|
||||||
|
wrap = 0;
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
rb_raise(rb_eDLError, "to_ptr should return a CPtr object");
|
rb_raise(rb_eDLError, "to_ptr should return a CPtr object");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
ptr = rb_dlptr_new(NUM2PTR(rb_Integer(val)), 0, NULL);
|
VALUE num = rb_Integer(val);
|
||||||
|
if (num != val) wrap = 0;
|
||||||
|
ptr = rb_dlptr_new(NUM2PTR(num), 0, NULL);
|
||||||
}
|
}
|
||||||
OBJ_INFECT(ptr, val);
|
OBJ_INFECT(ptr, val);
|
||||||
rb_iv_set(ptr, "wrapping", val);
|
if (wrap) RPTR_DATA(ptr)->wrap[0] = wrap;
|
||||||
return ptr;
|
return ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -199,6 +199,7 @@ struct cfunc_data {
|
|||||||
char *name;
|
char *name;
|
||||||
int type;
|
int type;
|
||||||
ID calltype;
|
ID calltype;
|
||||||
|
VALUE wrap;
|
||||||
};
|
};
|
||||||
extern ID rbdl_id_cdecl;
|
extern ID rbdl_id_cdecl;
|
||||||
extern ID rbdl_id_stdcall;
|
extern ID rbdl_id_stdcall;
|
||||||
@ -209,6 +210,7 @@ struct ptr_data {
|
|||||||
void *ptr;
|
void *ptr;
|
||||||
long size;
|
long size;
|
||||||
freefunc_t free;
|
freefunc_t free;
|
||||||
|
VALUE wrap[2];
|
||||||
};
|
};
|
||||||
|
|
||||||
#define RDL_HANDLE(obj) ((struct dl_handle *)(DATA_PTR(obj)))
|
#define RDL_HANDLE(obj) ((struct dl_handle *)(DATA_PTR(obj)))
|
||||||
|
@ -95,6 +95,11 @@ module DL
|
|||||||
buff = "9341"
|
buff = "9341"
|
||||||
qsort.call(buff, buff.size, 1, cb)
|
qsort.call(buff, buff.size, 1, cb)
|
||||||
assert_equal("1349", buff)
|
assert_equal("1349", buff)
|
||||||
|
|
||||||
|
bug4929 = '[ruby-core:37395]'
|
||||||
|
buff = "9341"
|
||||||
|
EnvUtil.under_gc_stress {qsort.call(buff, buff.size, 1, cb)}
|
||||||
|
assert_equal("1349", buff, bug4929)
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_qsort2()
|
def test_qsort2()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user