8000 [ruby/fiddle] closure: free resources when an exception is raised in … · ruby/ruby@a4ad6bd · GitHub
[go: up one dir, main page]

Skip to content

Commit a4ad6bd

Browse files
kouhsbt
authored andcommitted
[ruby/fiddle] closure: free resources when an exception is raised in Closure.new
GitHub: GH-102 ruby/fiddle@81a8a56239
1 parent 9f62768 commit a4ad6bd

File tree

1 file changed

+43
-13
lines changed

1 file changed

+43
-13
lines changed

ext/fiddle/closure.c

Lines changed: 43 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -235,9 +235,16 @@ get_raw(VALUE self)
235235
return closure;
236236
}
237237

238+
typedef struct {
239+
VALUE self;
240+
int argc;
241+
VALUE *argv;
242+
} initialize_data;
243+
238244
static VALUE
239-
initialize(int rbargc, VALUE argv[], VALUE self)
245+
initialize_body(VALUE user_data)
240246
{
247+
initialize_data *data = (initialize_data *)user_data;
241248
VALUE ret;
242249
VALUE args;
243250
VALUE normalized_args;
@@ -248,14 +255,14 @@ initialize(int rbargc, VALUE argv[], VALUE self)
248255
ffi_status result;
249256
int i, argc;
250257

251-
if (2 == rb_scan_args(rbargc, argv, "21", &ret, &args, &abi))
252-
abi = INT2NUM(FFI_DEFAULT_ABI);
258+
if (2 == rb_scan_args(data->argc, data->argv, "21", &ret, &args, &abi))
259+
abi = INT2NUM(FFI_DEFAULT_ABI);
253260

254261
Check_Type(args, T_ARRAY);
255262

256263
argc = RARRAY_LENINT(args);
257264

258-
TypedData_Get_Struct(self, fiddle_closure, &closure_data_type, cl);
265+
TypedData_Get_Struct(data->self, fiddle_closure, &closure_data_type, cl);
259266

260267
cl->argv = (ffi_type **)xcalloc(argc + 1, sizeof(ffi_type *));
261268

@@ -268,8 +275,8 @@ initialize(int rbargc, VALUE argv[], VALUE self)
268275
cl->argv[argc] = NULL;
269276

270277
ret = rb_fiddle_type_ensure(ret);
271-
rb_iv_set(self, "@ctype", ret);
272-
rb_iv_set(self, "@args", normalized_args);
278+
rb_iv_set(data->self, "@ctype", ret);
279+
rb_iv_set(data->self, "@args", normalized_args);
273280

274281
cif = &cl->cif;
275282
pcl = cl->pcl;
@@ -280,25 +287,48 @@ initialize(int rbargc, VALUE argv[], VALUE self)
280287
rb_fiddle_int_to_ffi_type(NUM2INT(ret)),
281288
cl->argv);
282289

283-
if (FFI_OK != result)
284-
rb_raise(rb_eRuntimeError, "error prepping CIF %d", result);
290+
if (FFI_OK != result) {
291+
rb_raise(rb_eRuntimeError, "error prepping CIF %d", result);
292+
}
285293

286294
#if USE_FFI_CLOSURE_ALLOC
287295
result = ffi_prep_closure_loc(pcl, cif, callback,
288-
(void *)self, cl->code);
296+
(void *)(data->self), cl->code);
289297
#else
290298
result = ffi_prep_closure(pcl, cif, callback, (void *)self);
291299
cl->code = (void *)pcl;
292300
i = mprotect(pcl, sizeof(*pcl), PROT_READ | PROT_EXEC);
293301
if (i) {
294-
rb_sys_fail("mprotect");
302+
rb_sys_fail("mprotect");
295303
}
296304
#endif
297305

298-
if (FFI_OK != result)
299-
rb_raise(rb_eRuntimeError, "error prepping closure %d", result);
306+
if (FFI_OK != result) {
307+
rb_raise(rb_eRuntimeError, "error prepping closure %d", result);
308+
}
309+
310+
return data->self;
311+
}
300312

301-
return self;
313+
static VALUE
314+
initialize_rescue(VALUE user_data, VALUE exception)
315+
{
316+
initialize_data *data = (initialize_data *)user_data;
317+
dealloc(RTYPEDDATA_DATA(data->self));
318+
RTYPEDDATA_DATA(data->self) = NULL;
319+
rb_exc_raise(exception);
320+
return data->self;
321+
}
322+
323+
static VALUE
324+
initialize(int argc, VALUE *argv, VALUE self)
325+
{
326+
initialize_data data;
327+
data.self = self;
328+
data.argc = argc;
329+
data.argv = argv;
330+
return rb_rescue(initialize_body, (VALUE)&data,
331+
initialize_rescue, (VALUE)&data);
302332
}
303333

304334
static VALUE

0 commit comments

Comments
 (0)
0