Skip to content

Commit 935b034

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_6@22538 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
1 parent 2af8e54 commit 935b034

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 21:50:29 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 00:29:05 2009 Nobuyoshi Nakada <nobu@ruby-lang.org>
214

315
* ext/extmk.rb (extmake): does not use both of makefile.rb and

eval.c

Lines changed: 48 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -10230,8 +10230,8 @@ rb_gc_abort_threads()
1023010230
} END_FOREACH_FROM(main_thread, th);
1023110231
}
1023210232

10233-
static void
10234-
thread_free(th)
10233+
static inline void
10234+
stack_free(th)
1023510235
rb_thread_t th;
1023610236
{
1023710237
if (th->stk_ptr) free(th->stk_ptr);
@@ -10240,6 +10240,13 @@ thread_free(th)
1024010240
if (th->bstr_ptr) free(th->bstr_ptr);
1024110241
th->bstr_ptr = 0;
1024210242
#endif
10243+
}
10244+
10245+
static void
10246+
thread_free(th)
10247+
rb_thread_t th;
10248+
{
10249+
stack_free(th);
1024310250
if (th->locals) st_free_table(th->locals);
1024410251
if (th->status != THREAD_KILLED) {
1024510252
if (th->prev) th->prev->next = th->next;
@@ -10532,8 +10539,7 @@ rb_thread_die(th)
1053210539
{
1053310540
th->thgroup = 0;
1053410541
th->status = THREAD_KILLED;
10535-
if (th->stk_ptr) free(th->stk_ptr);
10536-
th->stk_ptr = 0;
10542+
stack_free(th);
1053710543
}
1053810544

1053910545
static void
@@ -12776,6 +12782,38 @@ rb_thread_atfork()
1277612782
}
1277712783

1277812784

12785+
static void
12786+
cc_purge(cc)
12787+
rb_thread_t cc;
12788+
{
12789+
/* free continuation's stack if it has just died */
12790+
if (NIL_P(cc->thread)) return;
12791+
if (rb_thread_check(cc->thread)->status == THREAD_KILLED) {
12792+
cc->thread = Qnil;
12793+
rb_thread_die(cc); /* can't possibly activate this stack */
12794+
}
12795+
}
12796+
12797+
static void
12798+
cc_mark(cc)
12799+
rb_thread_t cc;
12800+
{
12801+
/* mark this continuation's stack only if its parent thread is still alive */
12802+
cc_purge(cc);
12803+
thread_mark(cc);
12804+
}
12805+
12806+
static rb_thread_t
12807+
rb_cont_check(data)
12808+
VALUE data;
12809+
{
12810+
if (TYPE(data) != T_DATA || RDATA(data)->dmark != (RUBY_DATA_FUNC)cc_mark) {
12811+
rb_raise(rb_eTypeError, "wrong argument type %s (expected Continuation)",
12812+
rb_obj_classname(data));
12813+
}
12814+
return (rb_thread_t)RDATA(data)->data;
12815+
}
12816+
1277912817
/*
1278012818
* Document-class: Continuation
1278112819
*
@@ -12850,14 +12888,16 @@ rb_callcc(self)
1285012888
struct RVarmap *vars;
1285112889

1285212890
THREAD_ALLOC(th);
12853-
cont = Data_Wrap_Struct(rb_cCont, thread_mark, thread_free, th);
12891+
/* must finish th initialization before any possible gc.
12892+
* brent@mbari.org */
12893+
th->thread = curr_thread->thread;
12894+
th->thgroup = cont_protect;
12895+
cont = Data_Wrap_Struct(rb_cCont, cc_mark, thread_free, th);
1285412896

1285512897
scope_dup(ruby_scope);
1285612898
for (tag=prot_tag; tag; tag=tag->prev) {
1285712899
scope_dup(tag->scope);
1285812900
}
12859-
th->thread = curr_thread->thread;
12860-
th->thgroup = cont_protect;
1286112901

1286212902
for (vars = ruby_dyna_vars; vars; vars = vars->next) {
1286312903
if (FL_TEST(vars, DVAR_DONT_RECYCLE)) break;
@@ -12894,7 +12934,7 @@ rb_cont_call(argc, argv, cont)
1289412934
VALUE *argv;
1289512935
VALUE cont;
1289612936
{
12897-
rb_thread_t th = rb_thread_check(cont);
12937+
rb_thread_t th = rb_cont_check(cont);
1289812938

1289912939
if (th->thread != curr_thread->thread) {
1290012940
rb_raise(rb_eRuntimeError, "continuation called across threads");
@@ -13070,10 +13110,6 @@ thgroup_add(group, thread)
1307013110

1307113111
rb_secure(4);
1307213112
th = rb_thread_check(thread);
13073-
if (!th->next || !th->prev) {
13074-
rb_raise(rb_eTypeError, "wrong argument type %s (expected Thread)",
13075-
rb_obj_classname(thread));
13076-
}
1307713113

1307813114
if (OBJ_FROZEN(group)) {
1307913115
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 186
44
#define RUBY_RELEASE_CODE 20090222
5-
#define RUBY_PATCHLEVEL 349
5+
#define RUBY_PATCHLEVEL 350
66

77
#define RUBY_VERSION_MAJOR 1
88
#define RUBY_VERSION_MINOR 8

0 commit comments

Comments
 (0)