Skip to content

Commit a4ad6bd

Browse files
kouhsbt
authored andcommitted
[ruby/fiddle] closure: free resources when an exception is raised in Closure.new
GitHub: rubyGH-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)
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