From 322642364af2fc44e73f1bf5b40b14f921cda3bc Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Mon, 11 May 2026 14:39:01 +0900 Subject: [PATCH] capi.md: document that dfree handlers must not re-enter the VM The `dfree` callback registered via `mrb_data_type.dfree` runs from inside GC sweep, so allocating Ruby objects, calling `mrb_funcall` / `mrb_yield`, raising exceptions, or otherwise re-entering the VM can trigger a recursive GC that revisits the same object and causes double-free (see #6316). Make the rule explicit in the "Wrapping C Structures" section. close #6316 Co-authored-by: Claude --- doc/guides/capi.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/doc/guides/capi.md b/doc/guides/capi.md index f5c24152e..bc91d9c47 100644 --- a/doc/guides/capi.md +++ b/doc/guides/capi.md @@ -381,6 +381,13 @@ mrb_define_method(mrb, point, "initialize", point_init, MRB_ARGS_REQ(2)); mrb_define_method(mrb, point, "x", point_x, MRB_ARGS_NONE()); ``` +**Do not call into mruby from a `dfree` handler.** The handler runs +from inside GC sweep; allocating Ruby objects, calling +`mrb_funcall`, `mrb_yield`, raising exceptions, or otherwise +re-entering the VM can trigger a recursive GC that revisits the +same object and causes double-free. Keep `dfree` to `mrb_free` / +plain C cleanup of the wrapped data only. + ## Exception Handling ### Raising Exceptions