Project

General

Profile

Actions

Bug #1150

closed

calling instance_eval in extended library cause exception

Added by arton (Akio Tajima) about 12 years ago. Updated almost 10 years ago.

Status:
Closed
Priority:
Normal
Target version:
ruby -v:
ruby 1.9.1p0 (2009-01-30 revision 21907) [i386-mswin32]
Backport:
[ruby-dev:37979]

Description

=begin
拡張ライブラリ内のメソッドでinstance_evalを呼び出すと、Can't eval on top of Fiber or Thread (RuntimeError)になります。
再現コードを以下に示します。
// cmodev.c
#include "ruby.h"
#include "extconf.h"
static VALUE cmodev;
static VALUE xtest_func(VALUE self, VALUE s)
{
return rb_funcall2(self, rb_intern("instance_eval"), 1, &s);
}
void Init_cmodev()
{
cmodev = rb_define_class("XTest", rb_cObject);
rb_define_method(cmodev, "xtest", xtest_func, 1);

}

#t.rb
require 'cmodev'
x = XTest.new
x.xtest("puts 'hello'")

実行例
c:\test\modev\test>ruby t.rb
t.rb:3:in instance_eval': Can't eval on top of Fiber or Thread (RuntimeError)
from t.rb:3:in
xtest'
from t.rb:3:in `'
=end

Actions #1

Updated by ko1 (Koichi Sasada) about 12 years ago

=begin
 ささだです.

Akio Tajima wrote::

拡張ライブラリ内のメソッドでinstance_evalを呼び出すと、Can't eval on top of Fiber or Thread (RuntimeError)になります。

 ご指摘ありがとうございます.バグでした.

Index: vm_core.h
===================================================================
--- vm_core.h (リビジョン 22272)
+++ vm_core.h (作業コピー)
@@ -593,10 +593,14 @@ int ruby_thread_has_gvl_p(void);
VALUE rb_make_backtrace(void);
typedef int rb_backtrace_iter_func(void *, const char *, int, const
char *);
VALUE rb_backtrace_each(rb_backtrace_iter_func *iter, void *arg);
+rb_control_frame_t *rb_vm_get_ruby_level_next_cfp(rb_thread_t *th,
rb_control_frame_t *cfp);

NOINLINE(void rb_gc_save_machine_context(rb_thread_t *));

Index: vm_eval.c
===================================================================
--- vm_eval.c (リビジョン 22272)
+++ vm_eval.c (作業コピー)
@@ -706,7 +706,7 @@ eval_string_with_cref(VALUE self, VALUE
th->base_block = &env->block;
}
else {

  • rb_control_frame_t *cfp = vm_get_ruby_level_caller_cfp(th, th->cfp);
  •  rb_control_frame_t *cfp = rb_vm_get_ruby_level_next_cfp(th, th->cfp);
    
    if (cfp != 0) {
    block = *RUBY_VM_GET_BLOCK_PTR_IN_CFP(cfp);
    

    Index: proc.c

    --- proc.c (リビジョン 22272)
    +++ proc.c (作業コピー)
    @@ -274,8 +274,6 @@ binding_clone(VALUE self)
    return bindval;
    }

-rb_control_frame_t *rb_vm_get_ruby_level_next_cfp(rb_thread_t *th,
rb_control_frame_t *cfp);
-
VALUE
rb_binding_new(void)
{

 ちなみに,本当に eval がやりたいんですかね.binding を考えなければ,

 rb_iseq_eval(rb_iseq_compile(VALUE src, VALUE file, VALUE line))

なんて手があります.が,まだこれは裏技(intern.h にないという意味)だ
な.1.9.2 までに整理しよう.これをいっぺんにやる API もほしいんですが,
名前が決められなくて.

--
// SASADA Koichi at atdot dot net

=end

Actions #2

Updated by yugui (Yuki Sonoda) almost 12 years ago

  • Status changed from Open to Closed
  • Assignee set to ko1 (Koichi Sasada)

=begin

=end

Actions

Also available in: Atom PDF