Skip to content

Commit cb016e3

Browse files
committed
merge revision(s) 21353:
* eval.c (cc_mark): frees the continuation's stack if its thread is dead to avoid recursive gc that segfaults. [ruby-core:13889] a patch by Brent Roman <brent AT mbari.org>. * eval.c (rb_cont_check): checks for valid continuation instance. * eval.c (rb_callcc): assigns th->thread before scope_dup() to avoid segfaults if this scope_dup() triggers a gc pass. a patch by Brent Roman <brent AT mbari.org>. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/ruby_1_8_7@22540 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
1 parent 6cec674 commit cb016e3

File tree

3 files changed

+61
-13
lines changed

3 files changed

+61
-13
lines changed

ChangeLog

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,15 @@
1+
Sun Feb 22 22:03:40 2009 Nobuyoshi Nakada <nobu@ruby-lang.org>
2+
3+
* eval.c (cc_mark): frees the continuation's stack if its thread
4+
is dead to avoid recursive gc that segfaults. [ruby-core:13889]
5+
a patch by Brent Roman <brent AT mbari.org>.
6+
7+
* eval.c (rb_cont_check): checks for valid continuation instance.
8+
9+
* eval.c (rb_callcc): assigns th->thread before scope_dup() to
10+
avoid segfaults if this scope_dup() triggers a gc pass.
11+
a patch by Brent Roman <brent AT mbari.org>.
12+
113
Sun Feb 22 21:43:34 2009 Nobuyoshi Nakada <nobu@ruby-lang.org>
214

315
* numeric.c (ruby_float_step): extracted from num_step().

eval.c

Lines changed: 48 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -10513,8 +10513,8 @@ rb_gc_abort_threads()
1051310513
} END_FOREACH_FROM(main_thread, th);
1051410514
}
1051510515

10516-
static void
10517-
thread_free(th)
10516+
static inline void
10517+
stack_free(th)
1051810518
rb_thread_t th;
1051910519
{
1052010520
if (th->stk_ptr) free(th->stk_ptr);
@@ -10523,6 +10523,13 @@ thread_free(th)
1052310523
if (th->bstr_ptr) free(th->bstr_ptr);
1052410524
th->bstr_ptr = 0;
1052510525
#endif
10526+
}
10527+
10528+
static void
10529+
thread_free(th)
10530+
rb_thread_t th;
10531+
{
10532+
stack_free(th);
1052610533
if (th->locals) st_free_table(th->locals);
1052710534
if (th->status != THREAD_KILLED) {
1052810535
if (th->prev) th->prev->next = th->next;
@@ -10815,8 +10822,7 @@ rb_thread_die(th)
1081510822
{
1081610823
th->thgroup = 0;
1081710824
th->status = THREAD_KILLED;
10818-
if (th->stk_ptr) free(th->stk_ptr);
10819-
th->stk_ptr = 0;
10825+
stack_free(th);
1082010826
}
1082110827

1082210828
static void
@@ -13006,6 +13012,38 @@ rb_thread_atfork()
1300613012
}
1300713013

1300813014

13015+
static void
13016+
cc_purge(cc)
13017+
rb_thread_t cc;
13018+
{
13019+
/* free continuation's stack if it has just died */
13020+
if (NIL_P(cc->thread)) return;
13021+
if (rb_thread_check(cc->thread)->status == THREAD_KILLED) {
13022+
cc->thread = Qnil;
13023+
rb_thread_die(cc); /* can't possibly activate this stack */
13024+
}
13025+
}
13026+
13027+
static void
13028+
cc_mark(cc)
13029+
rb_thread_t cc;
13030+
{
13031+
/* mark this continuation's stack only if its parent thread is still alive */
13032+
cc_purge(cc);
13033+
thread_mark(cc);
13034+
}
13035+
13036+
static rb_thread_t
13037+
rb_cont_check(data)
13038+
VALUE data;
13039+
{
13040+
if (TYPE(data) != T_DATA || RDATA(data)->dmark != (RUBY_DATA_FUNC)cc_mark) {
13041+
rb_raise(rb_eTypeError, "wrong argument type %s (expected Continuation)",
13042+
rb_obj_classname(data));
13043+
}
13044+
return (rb_thread_t)RDATA(data)->data;
13045+
}
13046+
1300913047
/*
1301013048
* Document-class: Continuation
1301113049
*
@@ -13080,14 +13118,16 @@ rb_callcc(self)
1308013118
struct RVarmap *vars;
1308113119

1308213120
THREAD_ALLOC(th);
13083-
cont = Data_Wrap_Struct(rb_cCont, thread_mark, thread_free, th);
13121+
/* must finish th initialization before any possible gc.
13122+
* brent@mbari.org */
13123+
th->thread = curr_thread->thread;
13124+
th->thgroup = cont_protect;
13125+
cont = Data_Wrap_Struct(rb_cCont, cc_mark, thread_free, th);
1308413126

1308513127
scope_dup(ruby_scope);
1308613128
for (tag=prot_tag; tag; tag=tag->prev) {
1308713129
scope_dup(tag->scope);
1308813130
}
13089-
th->thread = curr_thread->thread;
13090-
th->thgroup = cont_protect;
1309113131

1309213132
for (vars = ruby_dyna_vars; vars; vars = vars->next) {
1309313133
if (FL_TEST(vars, DVAR_DONT_RECYCLE)) break;
@@ -13124,7 +13164,7 @@ rb_cont_call(argc, argv, cont)
1312413164
VALUE *argv;
1312513165
VALUE cont;
1312613166
{
13127-
rb_thread_t th = rb_thread_check(cont);
13167+
rb_thread_t th = rb_cont_check(cont);
1312813168

1312913169
if (th->thread != curr_thread->thread) {
1313013170
rb_raise(rb_eRuntimeError, "continuation called across threads");
@@ -13300,10 +13340,6 @@ thgroup_add(group, thread)
1330013340

1330113341
rb_secure(4);
1330213342
th = rb_thread_check(thread);
13303-
if (!th->next || !th->prev) {
13304-
rb_raise(rb_eTypeError, "wrong argument type %s (expected Thread)",
13305-
rb_obj_classname(thread));
13306-
}
1330713343

1330813344
if (OBJ_FROZEN(group)) {
1330913345
rb_raise(rb_eThreadError, "can't move to the frozen thread group");

version.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
#define RUBY_RELEASE_DATE "2009-02-22"
33
#define RUBY_VERSION_CODE 187
44
#define RUBY_RELEASE_CODE 20090222
5-
#define RUBY_PATCHLEVEL 137
5+
#define RUBY_PATCHLEVEL 138
66

77
#define RUBY_VERSION_MAJOR 1
88
#define RUBY_VERSION_MINOR 8

0 commit comments

Comments
 (0)