eval.c: copy special exception
* eval.c (setup_exception): make unfrozen copy of special exception before setting up a cause. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@57415 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
7bf450d0c3
commit
54fa9f9e13
17
eval.c
17
eval.c
@ -470,6 +470,17 @@ sysstack_error_p(VALUE exc)
|
|||||||
return exc == sysstack_error || (!SPECIAL_CONST_P(exc) && RBASIC_CLASS(exc) == rb_eSysStackError);
|
return exc == sysstack_error || (!SPECIAL_CONST_P(exc) && RBASIC_CLASS(exc) == rb_eSysStackError);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline int
|
||||||
|
special_exception_p(rb_thread_t *th, VALUE exc)
|
||||||
|
{
|
||||||
|
enum ruby_special_exceptions i;
|
||||||
|
const VALUE *exceptions = th->vm->special_exceptions;
|
||||||
|
for (i = 0; i < ruby_special_error_count; ++i) {
|
||||||
|
if (exceptions[i] == exc) return TRUE;
|
||||||
|
}
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
setup_exception(rb_thread_t *th, int tag, volatile VALUE mesg, VALUE cause)
|
setup_exception(rb_thread_t *th, int tag, volatile VALUE mesg, VALUE cause)
|
||||||
{
|
{
|
||||||
@ -487,6 +498,9 @@ setup_exception(rb_thread_t *th, int tag, volatile VALUE mesg, VALUE cause)
|
|||||||
mesg = rb_exc_new(rb_eRuntimeError, 0, 0);
|
mesg = rb_exc_new(rb_eRuntimeError, 0, 0);
|
||||||
nocause = 0;
|
nocause = 0;
|
||||||
}
|
}
|
||||||
|
else if (special_exception_p(th, mesg)) {
|
||||||
|
mesg = ruby_vm_special_exception_copy(mesg);
|
||||||
|
}
|
||||||
if (cause != Qundef) {
|
if (cause != Qundef) {
|
||||||
exc_setup_cause(mesg, cause);
|
exc_setup_cause(mesg, cause);
|
||||||
}
|
}
|
||||||
@ -503,9 +517,6 @@ setup_exception(rb_thread_t *th, int tag, volatile VALUE mesg, VALUE cause)
|
|||||||
if (sysstack_error_p(mesg)) {
|
if (sysstack_error_p(mesg)) {
|
||||||
if (NIL_P(rb_attr_get(mesg, idBt))) {
|
if (NIL_P(rb_attr_get(mesg, idBt))) {
|
||||||
at = rb_vm_backtrace_object();
|
at = rb_vm_backtrace_object();
|
||||||
if (mesg == sysstack_error) {
|
|
||||||
mesg = ruby_vm_sysstack_error_copy();
|
|
||||||
}
|
|
||||||
rb_ivar_set(mesg, idBt, at);
|
rb_ivar_set(mesg, idBt, at);
|
||||||
rb_ivar_set(mesg, idBt_locations, at);
|
rb_ivar_set(mesg, idBt_locations, at);
|
||||||
}
|
}
|
||||||
|
@ -1575,7 +1575,7 @@ void rb_vm_pop_cfunc_frame(void);
|
|||||||
int rb_vm_add_root_module(ID id, VALUE module);
|
int rb_vm_add_root_module(ID id, VALUE module);
|
||||||
void rb_vm_check_redefinition_by_prepend(VALUE klass);
|
void rb_vm_check_redefinition_by_prepend(VALUE klass);
|
||||||
VALUE rb_yield_refine_block(VALUE refinement, VALUE refinements);
|
VALUE rb_yield_refine_block(VALUE refinement, VALUE refinements);
|
||||||
VALUE ruby_vm_sysstack_error_copy(void);
|
VALUE ruby_vm_special_exception_copy(VALUE);
|
||||||
PUREFUNC(st_table *rb_vm_fstring_table(void));
|
PUREFUNC(st_table *rb_vm_fstring_table(void));
|
||||||
|
|
||||||
|
|
||||||
|
@ -3463,5 +3463,25 @@ __END__
|
|||||||
assert_equal(["foo\n", "bar\n", "baz\n"], IO.readlines(t.path))
|
assert_equal(["foo\n", "bar\n", "baz\n"], IO.readlines(t.path))
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_closed_stream_in_rescue
|
||||||
|
100.times do
|
||||||
|
assert_nothing_raised(RuntimeError, /frozen IOError/) do
|
||||||
|
IO.pipe do |r, w|
|
||||||
|
th = Thread.start {r.close}
|
||||||
|
r.gets
|
||||||
|
rescue IOError
|
||||||
|
# swallow pending exceptions
|
||||||
|
begin
|
||||||
|
sleep 0.001
|
||||||
|
rescue IOError
|
||||||
|
retry
|
||||||
|
end
|
||||||
|
ensure
|
||||||
|
th.kill.join
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -22,17 +22,17 @@
|
|||||||
static rb_control_frame_t *vm_get_ruby_level_caller_cfp(const rb_thread_t *th, const rb_control_frame_t *cfp);
|
static rb_control_frame_t *vm_get_ruby_level_caller_cfp(const rb_thread_t *th, const rb_control_frame_t *cfp);
|
||||||
|
|
||||||
VALUE
|
VALUE
|
||||||
ruby_vm_sysstack_error_copy(void)
|
ruby_vm_special_exception_copy(VALUE exc)
|
||||||
{
|
{
|
||||||
VALUE e = rb_obj_alloc(rb_eSysStackError);
|
VALUE e = rb_obj_alloc(rb_class_real(RBASIC_CLASS(exc)));
|
||||||
rb_obj_copy_ivar(e, sysstack_error);
|
rb_obj_copy_ivar(e, exc);
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
vm_stackoverflow(void)
|
vm_stackoverflow(void)
|
||||||
{
|
{
|
||||||
rb_exc_raise(ruby_vm_sysstack_error_copy());
|
rb_exc_raise(ruby_vm_special_exception_copy(sysstack_error));
|
||||||
}
|
}
|
||||||
|
|
||||||
#if VM_CHECK_MODE > 0
|
#if VM_CHECK_MODE > 0
|
||||||
|
Loading…
x
Reference in New Issue
Block a user