[ruby/fiddle] closure: free resources when an exception is raised in Closure.new
GitHub: GH-102 https://github.com/ruby/fiddle/commit/81a8a56239
This commit is contained in:
parent
9f62768e51
commit
a4ad6bd9aa
@ -235,9 +235,16 @@ get_raw(VALUE self)
|
|||||||
return closure;
|
return closure;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
VALUE self;
|
||||||
|
int argc;
|
||||||
|
VALUE *argv;
|
||||||
|
} initialize_data;
|
||||||
|
|
||||||
static VALUE
|
static VALUE
|
||||||
initialize(int rbargc, VALUE argv[], VALUE self)
|
initialize_body(VALUE user_data)
|
||||||
{
|
{
|
||||||
|
initialize_data *data = (initialize_data *)user_data;
|
||||||
VALUE ret;
|
VALUE ret;
|
||||||
VALUE args;
|
VALUE args;
|
||||||
VALUE normalized_args;
|
VALUE normalized_args;
|
||||||
@ -248,14 +255,14 @@ initialize(int rbargc, VALUE argv[], VALUE self)
|
|||||||
ffi_status result;
|
ffi_status result;
|
||||||
int i, argc;
|
int i, argc;
|
||||||
|
|
||||||
if (2 == rb_scan_args(rbargc, argv, "21", &ret, &args, &abi))
|
if (2 == rb_scan_args(data->argc, data->argv, "21", &ret, &args, &abi))
|
||||||
abi = INT2NUM(FFI_DEFAULT_ABI);
|
abi = INT2NUM(FFI_DEFAULT_ABI);
|
||||||
|
|
||||||
Check_Type(args, T_ARRAY);
|
Check_Type(args, T_ARRAY);
|
||||||
|
|
||||||
argc = RARRAY_LENINT(args);
|
argc = RARRAY_LENINT(args);
|
||||||
|
|
||||||
TypedData_Get_Struct(self, fiddle_closure, &closure_data_type, cl);
|
TypedData_Get_Struct(data->self, fiddle_closure, &closure_data_type, cl);
|
||||||
|
|
||||||
cl->argv = (ffi_type **)xcalloc(argc + 1, sizeof(ffi_type *));
|
cl->argv = (ffi_type **)xcalloc(argc + 1, sizeof(ffi_type *));
|
||||||
|
|
||||||
@ -268,8 +275,8 @@ initialize(int rbargc, VALUE argv[], VALUE self)
|
|||||||
cl->argv[argc] = NULL;
|
cl->argv[argc] = NULL;
|
||||||
|
|
||||||
ret = rb_fiddle_type_ensure(ret);
|
ret = rb_fiddle_type_ensure(ret);
|
||||||
rb_iv_set(self, "@ctype", ret);
|
rb_iv_set(data->self, "@ctype", ret);
|
||||||
rb_iv_set(self, "@args", normalized_args);
|
rb_iv_set(data->self, "@args", normalized_args);
|
||||||
|
|
||||||
cif = &cl->cif;
|
cif = &cl->cif;
|
||||||
pcl = cl->pcl;
|
pcl = cl->pcl;
|
||||||
@ -280,25 +287,48 @@ initialize(int rbargc, VALUE argv[], VALUE self)
|
|||||||
rb_fiddle_int_to_ffi_type(NUM2INT(ret)),
|
rb_fiddle_int_to_ffi_type(NUM2INT(ret)),
|
||||||
cl->argv);
|
cl->argv);
|
||||||
|
|
||||||
if (FFI_OK != result)
|
if (FFI_OK != result) {
|
||||||
rb_raise(rb_eRuntimeError, "error prepping CIF %d", result);
|
rb_raise(rb_eRuntimeError, "error prepping CIF %d", result);
|
||||||
|
}
|
||||||
|
|
||||||
#if USE_FFI_CLOSURE_ALLOC
|
#if USE_FFI_CLOSURE_ALLOC
|
||||||
result = ffi_prep_closure_loc(pcl, cif, callback,
|
result = ffi_prep_closure_loc(pcl, cif, callback,
|
||||||
(void *)self, cl->code);
|
(void *)(data->self), cl->code);
|
||||||
#else
|
#else
|
||||||
result = ffi_prep_closure(pcl, cif, callback, (void *)self);
|
result = ffi_prep_closure(pcl, cif, callback, (void *)self);
|
||||||
cl->code = (void *)pcl;
|
cl->code = (void *)pcl;
|
||||||
i = mprotect(pcl, sizeof(*pcl), PROT_READ | PROT_EXEC);
|
i = mprotect(pcl, sizeof(*pcl), PROT_READ | PROT_EXEC);
|
||||||
if (i) {
|
if (i) {
|
||||||
rb_sys_fail("mprotect");
|
rb_sys_fail("mprotect");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (FFI_OK != result)
|
if (FFI_OK != result) {
|
||||||
rb_raise(rb_eRuntimeError, "error prepping closure %d", result);
|
rb_raise(rb_eRuntimeError, "error prepping closure %d", result);
|
||||||
|
}
|
||||||
|
|
||||||
return self;
|
return data->self;
|
||||||
|
}
|
||||||
|
|
||||||
|
static VALUE
|
||||||
|
initialize_rescue(VALUE user_data, VALUE exception)
|
||||||
|
{
|
||||||
|
initialize_data *data = (initialize_data *)user_data;
|
||||||
|
dealloc(RTYPEDDATA_DATA(data->self));
|
||||||
|
RTYPEDDATA_DATA(data->self) = NULL;
|
||||||
|
rb_exc_raise(exception);
|
||||||
|
return data->self;
|
||||||
|
}
|
||||||
|
|
||||||
|
static VALUE
|
||||||
|
initialize(int argc, VALUE *argv, VALUE self)
|
||||||
|
{
|
||||||
|
initialize_data data;
|
||||||
|
data.self = self;
|
||||||
|
data.argc = argc;
|
||||||
|
data.argv = argv;
|
||||||
|
return rb_rescue(initialize_body, (VALUE)&data,
|
||||||
|
initialize_rescue, (VALUE)&data);
|
||||||
}
|
}
|
||||||
|
|
||||||
static VALUE
|
static VALUE
|
||||||
|
Loading…
x
Reference in New Issue
Block a user