[#21508] eval BEGIN/END at runtime — "NAKAMURA, Hiroshi" <nakahiro@...>

なひです。

15 messages 2003/10/06

[#21616] access ENV on $SAFE==4 — Hidetoshi NAGAI <nagai@...>

永井@知能.九工大です.

44 messages 2003/10/14
[#21643] Re: access ENV on $SAFE==4 — matz@... (Yukihiro Matsumoto) 2003/10/20

まつもと ゆきひろです

[#21646] Re: access ENV on $SAFE==4 — TADA Tadashi <sho@...> 2003/10/20

ただただしです。

[#21656] Re: access ENV on $SAFE==4 — Hidetoshi NAGAI <nagai@...> 2003/10/20

永井@知能.九工大です.

[#21695] Re: access ENV on $SAFE==4 — Hidetoshi NAGAI <nagai@...> 2003/10/23

永井@知能.九工大です.

[#21696] Re: access ENV on $SAFE==4 — nobu.nakada@... 2003/10/23

なかだです。

[#21697] Re: access ENV on $SAFE==4 — Hidetoshi NAGAI <nagai@...> 2003/10/23

永井@知能.九工大です.

[#21698] Re: access ENV on $SAFE==4 — nobu.nakada@... 2003/10/23

なかだです。

[#21704] Re: access ENV on $SAFE==4 — Hidetoshi NAGAI <nagai@...> 2003/10/24

永井@知能.九工大です.

[#21712] Re: access ENV on $SAFE==4 — matz@... (Yukihiro Matsumoto) 2003/10/24

まつもと ゆきひろです

[#21713] Re: access ENV on $SAFE==4 — Hidetoshi NAGAI <nagai@...> 2003/10/24

永井@知能.九工大です.

[#21715] Re: access ENV on $SAFE==4 — matz@... (Yukihiro Matsumoto) 2003/10/25

まつもと ゆきひろです

[#21718] Re: access ENV on $SAFE==4 — Hidetoshi NAGAI <nagai@...> 2003/10/25

永井@知能.九工大です.

[#21720] Re: access ENV on $SAFE==4 — Hidetoshi NAGAI <nagai@...> 2003/10/25

永井@知能.九工大です.

[#21721] Re: access ENV on $SAFE==4 — matz@... (Yukihiro Matsumoto) 2003/10/25

まつもと ゆきひろです

[#21723] Re: access ENV on $SAFE==4 — Hidetoshi NAGAI <nagai@...> 2003/10/25

永井@知能.九工大です.

[#21727] Re: access ENV on $SAFE==4 — Hidetoshi NAGAI <nagai@...> 2003/10/26

永井@知能.九工大です.

[#21682] ruby-tk hangs when exception is raised — akira yamada <akira@...>

62 messages 2003/10/23
[#21683] Re: ruby-tk hangs when exception is raised — nobu.nakada@... 2003/10/23

なかだです。

[#21685] Re: ruby-tk hangs when exception is raised — akira yamada / やまだあきら <akira@...> 2003/10/23

[#21687] Re: ruby-tk hangs when exception is raised — Hidetoshi NAGAI <nagai@...> 2003/10/23

永井@知能.九工大です.

[#21688] Re: ruby-tk hangs when exception is raised — akira yamada / やまだあきら <akira@...> 2003/10/23

[#21691] Re: ruby-tk hangs when exception is raised — Hidetoshi NAGAI <nagai@...> 2003/10/23

永井@知能.九工大です.

[#21693] Re: ruby-tk hangs when exception is raised — akira yamada / やまだあきら <akira@...> 2003/10/23

[#21694] Re: ruby-tk hangs when exception is raised — Hidetoshi NAGAI <nagai@...> 2003/10/23

永井@知能.九工大です.

[#21736] Re: ruby-tk hangs when exception is raised — Hidetoshi NAGAI <nagai@...> 2003/10/28

永井@知能.九工大です.

[#21744] Re: ruby-tk hangs when exception is raised — akira yamada / やまだあきら <akira@...> 2003/10/28

[#21797] Re: ruby-tk hangs when exception is raised — Hidetoshi NAGAI <nagai@...> 2003/10/31

永井@知能.九工大です.

[#21801] Re: ruby-tk hangs when exception is raised — Hidetoshi NAGAI <nagai@...> 2003/11/01

永井@知能.九工大です.

[#21825] Re: ruby-tk hangs when exception is raised — Hidetoshi NAGAI <nagai@...> 2003/11/04

永井@知能.九工大です.

[#21833] pthread trouble on tcltklib (Re: ruby-tk hangs when exception is raised) — Hidetoshi NAGAI <nagai@...> 2003/11/05

永井@知能.九工大です.

[#21835] Re: pthread trouble on tcltklib — Hidetoshi NAGAI <nagai@...> 2003/11/05

永井@知能.九工大です.

[#21900] Re: pthread trouble on tcltklib — nobu.nakada@... 2003/11/11

なかだです。

[#21901] Re: pthread trouble on tcltklib — Hidetoshi NAGAI <nagai@...> 2003/11/12

永井@知能.九工大です.

[#21905] Re: pthread trouble on tcltklib — nobu.nakada@... 2003/11/12

なかだです。

[#21908] Re: pthread trouble on tcltklib — Hidetoshi NAGAI <nagai@...> 2003/11/12

永井@知能.九工大です.

[#21914] Re: pthread trouble on tcltklib — nobu.nakada@... 2003/11/12

なかだです。

[#21915] Re: pthread trouble on tcltklib — Hidetoshi NAGAI <nagai@...> 2003/11/12

永井@知能.九工大です.

[#21916] Re: pthread trouble on tcltklib — nobu.nakada@... 2003/11/12

なかだです。

[#21922] Re: pthread trouble on tcltklib — Hidetoshi NAGAI <nagai@...> 2003/11/14

永井@知能.九工大です.

[#21929] Re: pthread trouble on tcltklib — Tietew <tietew-ml-ruby-dev@...> 2003/11/17

[#21930] Re: pthread trouble on tcltklib — nobu.nakada@... 2003/11/17

なかだです。

[#21931] Re: pthread trouble on tcltklib — Hidetoshi NAGAI <nagai@...> 2003/11/17

永井@知能.九工大です.

[#21934] Re: pthread trouble on tcltklib — nobu.nakada@... 2003/11/17

なかだです。

[#21937] Re: pthread trouble on tcltklib — Hidetoshi NAGAI <nagai@...> 2003/11/17

永井@知能.九工大です.

[#21952] Re: pthread trouble on tcltklib — matz@... (Yukihiro Matsumoto) 2003/11/18

まつもと ゆきひろです

[#21957] Re: pthread trouble on tcltklib — Hidetoshi NAGAI <nagai@...> 2003/11/19

永井@知能.九工大です.

[#21958] Re: pthread trouble on tcltklib — Tietew <tietew-ml-ruby-dev@...> 2003/11/19

[#21959] Re: pthread trouble on tcltklib — Hidetoshi NAGAI <nagai@...> 2003/11/19

永井@知能.九工大です.

[#21960] Re: pthread trouble on tcltklib — Tietew <tietew-ml-ruby-dev@...> 2003/11/19

[#21707] drb Hash#each — matz@... (Yukihiro Matsumoto)

まつもと ゆきひろです

22 messages 2003/10/24
[#21708] Re: drb Hash#each — m_seki@... 2003/10/24

[#21709] Re: drb Hash#each — matz@... (Yukihiro Matsumoto) 2003/10/24

まつもと ゆきひろです

[#21710] Re: drb Hash#each — m_seki@... 2003/10/24

[#21747] ruby 1.8.1 preview1 schedule — matz@... (Yukihiro Matsumoto)

関係者各位、

25 messages 2003/10/29

[ruby-dev:21568] Re: rewinding for Thread

From: nobu.nakada@...
Date: 2003-10-09 04:53:29 UTC
List: ruby-dev #21568
なかだです。

At Thu, 9 Oct 2003 12:41:07 +0900,
Tietew wrote:
> > 以前、スレッドの中でスレッドを作るというのを繰り返すとstack
> > level too deepになる、という話があったような気がするので、Proc
> > を作ってからトップレベルまで巻き戻してブランチするようにしてみ
> > ました。
> 
> パッチを見たのですが,ruby_exec を呼ばずに直接 rb_load や 
> rb_funcall を呼ぶような組み込み Ruby で困ります。

巻き戻すのはPROT_THREADがあるときだけなので、なければそのままス
レッドを作るはずです。

> TAG_THREAD を捕まえて処理するような rb_protect_thread みたいな関
> 数を作ればいいのかな。それとも rb_protect が一括処理?

rb_protect()は任意のコードを実行できるので、そこから呼ばれた関
数のローカル変数のポインタをrb_thread_create()に渡すこともでき
ますから、かえって危険です。逆に、スタックを巻き戻さないように
上位のPROT_THREADを隠さないとまずいかも知れません。


Index: eval.c
===================================================================
RCS file: /cvs/ruby/src/ruby/eval.c,v
retrieving revision 1.554
diff -u -2 -p -r1.554 eval.c
--- eval.c	9 Oct 2003 01:51:08 -0000	1.554
+++ eval.c	9 Oct 2003 04:36:53 -0000
@@ -854,4 +854,11 @@ static struct tag *prot_tag;
 #define PROT_PCALL  INT2FIX(3)	/* 7 */
 
+#define PUSH_THREAD_TAG() PUSH_TAG(PROT_THREAD); \
+do { \
+    if (!new_thread.tag) new_thread.tag = prot_tag
+#define POP_THREAD_TAG() \
+    if (new_thread.tag == prot_tag) new_thread.tag = 0; \
+} while (0)
+
 #define EXEC_TAG()    (FLUSH_REGISTER_WINDOWS, setjmp(prot_tag->buf))
 
@@ -876,6 +883,14 @@ static struct tag *prot_tag;
 #define TAG_THROW	0x7
 #define TAG_FATAL	0x8
+#define TAG_THREAD	0x9
 #define TAG_MASK	0xf
 
+static struct {
+    rb_thread_t thread;
+    VALUE proc;
+    void *arg;
+    struct tag *tag;
+} new_thread;
+
 VALUE ruby_class;
 static VALUE ruby_wrapper;	/* security wrapper */
@@ -1135,4 +1150,6 @@ void Init_heap _((void));
 void Init_ext _((void));
 
+NORETURN(static void rb_thread_start_1 _((void)));
+
 void
 ruby_init()
@@ -1165,5 +1182,5 @@ ruby_init()
     SCOPE_SET(SCOPE_PRIVATE);
 
-    PUSH_TAG(PROT_NONE);
+    PUSH_THREAD_TAG();
     if ((state = EXEC_TAG()) == 0) {
 	rb_call_inits();
@@ -1179,5 +1196,8 @@ ruby_init()
 	ALLOW_INTS;
     }
-    POP_TAG();
+    else if (state == TAG_THREAD) {
+	rb_thread_start_1();
+    }
+    POP_THREAD_TAG();
     if (state) {
 	error_print();
@@ -1291,8 +1311,11 @@ ruby_options(argc, argv)
 
     Init_stack((void*)&state);
-    PUSH_TAG(PROT_NONE);
+    PUSH_THREAD_TAG();
     if ((state = EXEC_TAG()) == 0) {
 	ruby_process_options(argc, argv);
     }
+    else if (state == TAG_THREAD) {
+	rb_thread_start_1();
+    }
     if (state) {
 	trace_func = 0;
@@ -1300,5 +1323,5 @@ ruby_options(argc, argv)
 	exit(error_handle(state));
     }
-    POP_TAG();
+    POP_THREAD_TAG();
 }
 
@@ -1362,5 +1385,5 @@ ruby_exec()
 
     Init_stack((void*)&tmp);
-    PUSH_TAG(PROT_NONE);
+    PUSH_THREAD_TAG();
     PUSH_ITER(ITER_NOT);
     /* default visibility is private at toplevel */
@@ -1369,6 +1392,9 @@ ruby_exec()
 	eval_node(ruby_top_self, ruby_eval_tree);
     }
+    else if (state == TAG_THREAD) {
+	rb_thread_start_1();
+    }
     POP_ITER();
-    POP_TAG();
+    POP_THREAD_TAG();
     return state;
 }
@@ -1435,13 +1461,16 @@ rb_eval_string_protect(str, state)
     int status;
 
-    PUSH_TAG(PROT_NONE);
+    PUSH_THREAD_TAG();
     if ((status = EXEC_TAG()) == 0) {
 	result = rb_eval_string(str);
     }
-    POP_TAG();
+    POP_THREAD_TAG();
     if (state) {
 	*state = status;
     }
     if (status != 0) {
+	if (status == TAG_THREAD) {
+	    rb_thread_start_1();
+	}
 	return Qnil;
     }
@@ -4583,9 +4612,12 @@ rb_protect(proc, data, state)
     VALUE result = Qnil;	/* OK */
     int status;
+    struct tag *volatile thread_tag = new_thread.tag;
 
     PUSH_TAG(PROT_NONE);
+    new_thread.tag = 0;
     if ((status = EXEC_TAG()) == 0) {
 	result = (*proc)(data);
     }
+    new_thread.tag = thread_tag;
     POP_TAG();
     if (state) {
@@ -5832,9 +5864,9 @@ rb_load_protect(fname, wrap, state)
     int status;
 
-    PUSH_TAG(PROT_NONE);
+    PUSH_THREAD_TAG();
     if ((status = EXEC_TAG()) == 0) {
 	rb_load(fname, wrap);
     }
-    POP_TAG();
+    POP_THREAD_TAG();
     if (state) *state = status;
 }
@@ -6930,6 +6962,11 @@ proc_alloc(klass, proc)
     }
 
-    if (!proc && ruby_block->block_obj && CLASS_OF(ruby_block->block_obj) == klass) {
-	return ruby_block->block_obj;
+    if (!proc && ruby_block->block_obj) {
+	VALUE obj = ruby_block->block_obj;
+	if (CLASS_OF(obj) != klass) {
+	    obj = proc_clone(obj);
+	    RBASIC(obj)->klass = klass;
+	}
+	return obj;
     }
     block = Data_Make_Struct(klass, struct BLOCK, blk_mark, blk_free, data);
@@ -7205,10 +7242,10 @@ proc_binding(proc)
 }
 
-static VALUE
-block_pass(self, node)
-    VALUE self;
-    NODE *node;
+VALUE
+rb_block_pass(func, arg, proc)
+    VALUE (*func) _((VALUE));
+    VALUE arg;
+    VALUE proc;
 {
-    VALUE proc = rb_eval(self, node->nd_body);	/* OK */
     VALUE b;
     struct BLOCK * volatile old_block;
@@ -7222,5 +7259,5 @@ block_pass(self, node)
     if (NIL_P(proc)) {
 	PUSH_ITER(ITER_NOT);
-	result = rb_eval(self, node->nd_iter);
+	result = (*func)(arg);
 	POP_ITER();
 	return result;
@@ -7243,5 +7280,5 @@ block_pass(self, node)
     if (ruby_block && ruby_block->block_obj == proc) {
 	PUSH_ITER(ITER_PRE);
-	result = rb_eval(self, node->nd_iter);
+	result = (*func)(arg);
 	POP_ITER();
 	return result;
@@ -7267,5 +7304,5 @@ block_pass(self, node)
 	if (safe > ruby_safe_level)
 	    ruby_safe_level = safe;
-	result = rb_eval(self, node->nd_iter);
+	result = (*func)(arg);
     }
     else if (state == TAG_BREAK && TAG_DST()) {
@@ -7296,4 +7333,28 @@ block_pass(self, node)
 }
 
+struct block_arg {
+    VALUE self;
+    NODE *iter;
+};
+
+static VALUE
+call_block(arg)
+    struct block_arg *arg;
+{
+    return rb_eval(arg->self, arg->iter);
+}
+
+static VALUE
+block_pass(self, node)
+    VALUE self;
+    NODE *node;
+{
+    struct block_arg arg;
+    arg.self = self;
+    arg.iter = node->nd_iter;
+    return rb_block_pass((VALUE (*)_((VALUE)))call_block,
+			 (VALUE)&arg, rb_eval(self, node->nd_body));
+}
+
 struct METHOD {
     VALUE klass, rklass;
@@ -9402,4 +9463,22 @@ rb_thread_stop_timer()
 #endif
 
+NORETURN(static void rb_thread_terminated _((rb_thread_t, int, enum thread_status)));
+static VALUE rb_thread_yield _((VALUE, rb_thread_t));
+
+static void
+thread_inseart(th)
+    rb_thread_t th;
+{
+    if (!th->next) {
+	/* merge in thread list */
+	th->prev = curr_thread;
+	curr_thread->next->prev = th;
+	th->next = curr_thread->next;
+	curr_thread->next = th;
+	th->priority = curr_thread->priority;
+	th->thgroup = curr_thread->thgroup;
+    }
+}
+
 static VALUE
 rb_thread_start_0(fn, arg, th)
@@ -9432,5 +9511,11 @@ rb_thread_start_0(fn, arg, th)
 
     if (THREAD_SAVE_CONTEXT(curr_thread)) {
-	return th_save->thread;
+	return th->thread;
+    }
+    if (fn == rb_thread_yield && new_thread.tag) {
+	new_thread.thread = th;
+	new_thread.proc = rb_block_proc();
+	new_thread.arg = arg;
+	longjmp(new_thread.tag->buf, TAG_THREAD);
     }
 
@@ -9444,15 +9529,7 @@ rb_thread_start_0(fn, arg, th)
     scope_dup(ruby_scope);
 
-    if (!th->next) {
-	/* merge in thread list */
-	th->prev = curr_thread;
-	curr_thread->next->prev = th;
-	th->next = curr_thread->next;
-	curr_thread->next = th;
-	th->priority = curr_thread->priority;
-	th->thgroup = curr_thread->thgroup;
-    }
+    thread_inseart(th);
 
-    PUSH_TAG(PROT_THREAD);
+    PUSH_THREAD_TAG();
     if ((state = EXEC_TAG()) == 0) {
 	if (THREAD_SAVE_CONTEXT(th) == 0) {
@@ -9465,5 +9542,5 @@ rb_thread_start_0(fn, arg, th)
     }
     th = th_save;
-    POP_TAG();
+    POP_THREAD_TAG();
     status = th->status;
 
@@ -9480,4 +9557,14 @@ rb_thread_start_0(fn, arg, th)
     }
 
+    rb_thread_terminated(th, state, status);
+    return 0;			/* not reached */
+}
+
+static void
+rb_thread_terminated(th, state, status)
+    rb_thread_t th;
+    int state;
+    enum thread_status status;
+{
     if (state && status != THREAD_TO_KILL && !NIL_P(ruby_errinfo)) {
 	th->flags |= THREAD_RAISED;
@@ -9509,5 +9596,49 @@ rb_thread_start_0(fn, arg, th)
     rb_thread_schedule();
     ruby_stop(0);		/* last thread termination */
-    return 0;			/* not reached */
+}
+
+struct thread_yield_arg {
+    VALUE arg;
+    rb_thread_t thread;
+};
+
+static VALUE
+rb_thread_yield_0(arg)
+    struct thread_yield_arg *arg;
+{
+    return rb_thread_yield(arg->arg, arg->thread);
+}
+
+static void
+rb_thread_start_1()
+{
+    rb_thread_t th = new_thread.thread;
+    VALUE proc = new_thread.proc;
+    struct thread_yield_arg arg;
+    enum thread_status status;
+    int state;
+
+    arg.arg = (VALUE)new_thread.arg;
+    arg.thread = th;
+
+    thread_inseart(th);
+
+    PUSH_TAG(PROT_NONE);
+    if ((state = EXEC_TAG()) == 0) {
+	if (THREAD_SAVE_CONTEXT(th) == 0) {
+	    curr_thread = th;
+	    th->result = rb_block_pass(rb_thread_yield_0, (VALUE)&arg, proc);
+	}
+    }
+    else if (TAG_DST()) {
+	th->result = prot_tag->retval;
+    }
+    th = arg.thread;
+    POP_TAG();
+    status = th->status;
+
+    if (th == main_thread) ruby_stop(state);
+    rb_thread_remove(th);
+    rb_thread_terminated(th, state, status);
 }
 
@@ -10240,4 +10371,5 @@ rb_f_throw(argc, argv)
 	}
 	if (tt->tag == PROT_THREAD) {
+	    if (curr_thread == main_thread) goto uncaught;
 	    rb_raise(rb_eThreadError, "uncaught throw `%s' in thread 0x%lx",
 		     rb_id2name(SYM2ID(tag)),
@@ -10247,4 +10379,5 @@ rb_f_throw(argc, argv)
     }
     if (!tt) {
+      uncaught:
 	rb_name_error(SYM2ID(tag), "uncaught throw `%s'", rb_id2name(SYM2ID(tag)));
     }


-- 
--- 僕の前にBugはない。
--- 僕の後ろにBugはできる。
    中田 伸悦

In This Thread