I suspect this may be due to the TypeError occurring during the rescue handling. One possibility is to preprocess the list of exception classes to make sure they are all classes or modules. This is different than the ruby-level rescue clause, which doesn't execute the rescue list expression unless an exception is raised, but since rb_rescue2
needs to be passed a va_list
of VALUE
s, it may be acceptable.
Can you try this patch and see if it fixes the issue:
diff --git a/eval.c b/eval.c
index 55ac8b4eac..1b05d3a10a 100644
--- a/eval.c
+++ b/eval.c
@@ -1012,6 +1012,15 @@ rb_vrescue2(VALUE (* b_proc) (VALUE), VALUE data1,
rb_control_frame_t *volatile cfp = ec->cfp;
volatile VALUE result = Qfalse;
volatile VALUE e_info = ec->errinfo;
+ VALUE eclass;
+ va_list args_check;
+
+ va_copy(args_check, args);
+ while ((eclass = va_arg(args_check, VALUE)) != 0) {
+ if (!(RB_TYPE_P(eclass, T_CLASS) || RB_TYPE_P(eclass, T_MODULE))) {
+ rb_raise(rb_eTypeError, "class or module required");
+ }
+ }
EC_PUSH_TAG(ec);
if ((state = EC_EXEC_TAG()) == TAG_NONE) {
@@ -1032,7 +1041,6 @@ rb_vrescue2(VALUE (* b_proc) (VALUE), VALUE data1,
if (state == TAG_RAISE) {
int handle = FALSE;
- VALUE eclass;
while ((eclass = va_arg(args, VALUE)) != 0) {
if (rb_obj_is_kind_of(ec->errinfo, eclass)) {
This uses va_copy
, which should be acceptable now because it is in C99. https://bugs.ruby-lang.org/projects/ruby-master/wiki/C99 links to a work around that can be used in Ruby <2.7 (before we switched to allowing C99 features), in case we need to backport this to Ruby 2.6.