diff options
author | Sutou Kouhei <kou@clear-code.com> | 2022-09-14 12:59:13 +0900 |
---|---|---|
committer | Hiroshi SHIBATA <hsbt@ruby-lang.org> | 2022-10-07 15:18:51 +0900 |
commit | 255e617bc38f714c943c932e7df2b709313fd6bf (patch) | |
tree | 7c29170acba0ebce434cce22c0bfe34774ac7117 /ext/fiddle/closure.c | |
parent | 191b91f47a1557b7178072e2a607105d5449e2ef (diff) |
[ruby/fiddle] Add Fiddle::Closure.create and Fiddle::Closure.free
GitHub: fix GH-102
It's for freeing a closure explicitly.
We can't use Fiddle::Closure before we fork the process. If we do it,
the process may be crashed with SELinux.
See https://github.com/ruby/fiddle/issues/102#issuecomment-1241763091
for details.
Reported by Vít Ondruch. Thanks!!!
https://github.com/ruby/fiddle/commit/a0ccc6bb1b
Diffstat (limited to 'ext/fiddle/closure.c')
-rw-r--r-- | ext/fiddle/closure.c | 55 |
1 files changed, 48 insertions, 7 deletions
diff --git a/ext/fiddle/closure.c b/ext/fiddle/closure.c index 2d340297d5..694ef90b7f 100644 --- a/ext/fiddle/closure.c +++ b/ext/fiddle/closure.c @@ -224,6 +224,17 @@ allocate(VALUE klass) return i; } +static fiddle_closure * +get_raw(VALUE self) +{ + fiddle_closure *closure; + TypedData_Get_Struct(self, fiddle_closure, &closure_data_type, closure); + if (!closure) { + rb_raise(rb_eArgError, "already freed: %+"PRIsVALUE, self); + } + return closure; +} + static VALUE initialize(int rbargc, VALUE argv[], VALUE self) { @@ -293,14 +304,28 @@ initialize(int rbargc, VALUE argv[], VALUE self) static VALUE to_i(VALUE self) { - fiddle_closure * cl; - void *code; - - TypedData_Get_Struct(self, fiddle_closure, &closure_data_type, cl); + fiddle_closure *closure = get_raw(self); + return PTR2NUM(closure->code); +} - code = cl->code; +static VALUE +closure_free(VALUE self) +{ + fiddle_closure *closure; + TypedData_Get_Struct(self, fiddle_closure, &closure_data_type, closure); + if (closure) { + dealloc(closure); + RTYPEDDATA_DATA(self) = NULL; + } + return RUBY_Qnil; +} - return PTR2NUM(code); +static VALUE +closure_freed_p(VALUE self) +{ + fiddle_closure *closure; + TypedData_Get_Struct(self, fiddle_closure, &closure_data_type, closure); + return closure ? RUBY_Qfalse : RUBY_Qtrue; } void @@ -353,8 +378,24 @@ Init_fiddle_closure(void) /* * Document-method: to_i * - * Returns the memory address for this closure + * Returns the memory address for this closure. */ rb_define_method(cFiddleClosure, "to_i", to_i, 0); + + /* + * Document-method: free + * + * Free this closure explicitly. You can't use this closure anymore. + * + * If this closure is already freed, this does nothing. + */ + rb_define_method(cFiddleClosure, "free", closure_free, 0); + + /* + * Document-method: freed? + * + * Whether this closure was freed explicitly. + */ + rb_define_method(cFiddleClosure, "freed?", closure_freed_p, 0); } /* vim: set noet sw=4 sts=4 */ |