summaryrefslogtreecommitdiff
path: root/ext/fiddle/closure.c
diff options
context:
space:
mode:
authorSutou Kouhei <kou@clear-code.com>2022-09-14 12:59:13 +0900
committerHiroshi SHIBATA <hsbt@ruby-lang.org>2022-10-07 15:18:51 +0900
commit255e617bc38f714c943c932e7df2b709313fd6bf (patch)
tree7c29170acba0ebce434cce22c0bfe34774ac7117 /ext/fiddle/closure.c
parent191b91f47a1557b7178072e2a607105d5449e2ef (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.c55
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 */