Skip to content

Commit 81a8a56

Browse files
committed
closure: free resources when an exception is raised in Closure.new
GitHub: GH-102
1 parent b2fef17 commit 81a8a56

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
@@ -237,9 +237,16 @@ get_raw(VALUE self)
237237
return closure;
238238
}
239239

240+
typedef struct {
241+
VALUE self;
242+
int argc;
243+
VALUE *argv;
244+
} initialize_data;
245+
240246
static VALUE
241-
initialize(int rbargc, VALUE argv[], VALUE self)
247+
initialize_body(VALUE user_data)
242248
{
249+
initialize_data *data = (initialize_data *)user_data;
243250
VALUE ret;
244251
VALUE args;
245252
VALUE normalized_args;
@@ -250,14 +257,14 @@ initialize(int rbargc, VALUE argv[], VALUE self)
250257
ffi_status result;
251258
int i, argc;
252259

253-
if (2 == rb_scan_args(rbargc, argv, "21", &ret, &args, &abi))
254-
abi = INT2NUM(FFI_DEFAULT_ABI);
260+
if (2 == rb_scan_args(data->argc, data->argv, "21", &ret, &args, &abi))
261+
abi = INT2NUM(FFI_DEFAULT_ABI);
255262

256263
Check_Type(args, T_ARRAY);
257264

258265
argc = RARRAY_LENINT(args);
259266

260-
TypedData_Get_Struct(self, fiddle_closure, &closure_data_type, cl);
267+
TypedData_Get_Struct(data->self, fiddle_closure, &closure_data_type, cl);
261268

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

@@ -270,8 +277,8 @@ initialize(int rbargc, VALUE argv[], VALUE self)
270277
cl->argv[argc] = NULL;
271278

272279
ret = rb_fiddle_type_ensure(ret);
273-
rb_iv_set(self, "@ctype", ret);
274-
rb_iv_set(self, "@args", normalized_args);
280+
rb_iv_set(data->self, "@ctype", ret);
281+
rb_iv_set(data->self, "@args", normalized_args);
275282

276283
cif = &cl->cif;
277284
pcl = cl->pcl;
@@ -282,25 +289,48 @@ initialize(int rbargc, VALUE argv[], VALUE self)
282289
rb_fiddle_int_to_ffi_type(NUM2INT(ret)),
283290
cl->argv);
284291

285-
if (FFI_OK != result)
286-
rb_raise(rb_eRuntimeError, "error prepping CIF %d", result);
292+
if (FFI_OK != result) {
293+
rb_raise(rb_eRuntimeError, "error prepping CIF %d", result);
294+
}
287295

288296
#if USE_FFI_CLOSURE_ALLOC
289297
result = ffi_prep_closure_loc(pcl, cif, callback,
290-
(void *)self, cl->code);
298+
(void *)(data->self), cl->code);
291299
#else
292300
result = ffi_prep_closure(pcl, cif, callback, (void *)self);
293301
cl->code = (void *)pcl;
294302
i = mprotect(pcl, sizeof(*pcl), PROT_READ | PROT_EXEC);
295303
if (i) {
296-
rb_sys_fail("mprotect");
304+
rb_sys_fail("mprotect");
297305
}
298306
#endif
299307

300-
if (FFI_OK != result)
301-
rb_raise(rb_eRuntimeError, "error prepping closure %d", result);
308+
if (FFI_OK != result) {
309+
rb_raise(rb_eRuntimeError, "error prepping closure %d", result);
310+
}
311+
312+
return data->self;
313+
}
302314

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

306336
static VALUE

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy