[#21482] begin/rescue/else syntax is broken — akira yamada <akira@...>
[#21498] test/ChangeLog ? lib/ChangeLog — "NAKAMURA, Hiroshi" <nakahiro@...>
なひです。
[#21499] File#path on closed file. — Tanaka Akira <akr@...17n.org>
ふと、
そういえば、
まつもと ゆきひろです
[#21508] eval BEGIN/END at runtime — "NAKAMURA, Hiroshi" <nakahiro@...>
なひです。
なひです。
新井です。
[#21511] return value of freeze — Tanaka Akira <akr@...17n.org>
ふと、freeze を使って思ったのですが、これの返値は何なんでしょうか?
[#21531] O_ACCMODE — Tanaka Akira <akr@...17n.org>
POSIX において fcntl.h に定義されている、O_ACCMODE が欲しくなったので
西山和広です。
In article <20031007220838.CC51.ZN@mbf.nifty.com>,
[#21543] Enumerator — "Akinori MUSHA" <knu@...>
1.8.0 のtきは標準ライブラリ入りについて異論はなかったものの
新井です。
[#21556] rewinding for Thread — nobu.nakada@...
なかだです。
まつもと ゆきひろです
なかだです。
まつもと ゆきひろです
[#21557] at_exist and safe level — Tanaka Akira <akr@...17n.org>
% ruby -ve '$SAFE = x = 1; at_exit { p $SAFE; p x }'
[#21572] core dump in rb_thread_schedule — Tanaka Akira <akr@...17n.org>
今日、cvs update したら、rb_thread_schedule で core を吐くようになったのですが、
まつもと ゆきひろです
なかだです。
In article <200310090901.h9991gfA004660@sharui.nakada.kanuma.tochigi.jp>,
In article <87ekxmojwc.fsf@serein.a02.aist.go.jp>,
[#21590] extend with marshal_dump/marshal_load — "NAKAMURA, Hiroshi" <nakahiro@...>
なひです。
[#21607] autoload の patch は取り込まれないんでしょうか? — Hidetoshi NAGAI <nagai@...>
永井@知能.九工大です.
[#21616] access ENV on $SAFE==4 — Hidetoshi NAGAI <nagai@...>
永井@知能.九工大です.
まつもと ゆきひろです
ただただしです。
永井@知能.九工大です.
永井@知能.九工大です.
なかだです。
永井@知能.九工大です.
なかだです。
永井@知能.九工大です.
まつもと ゆきひろです
永井@知能.九工大です.
まつもと ゆきひろです
永井@知能.九工大です.
永井@知能.九工大です.
まつもと ゆきひろです
永井@知能.九工大です.
永井@知能.九工大です.
まつもと ゆきひろです
ただただしです。
まつもと ゆきひろです
[#21632] SEGV (test_drb.rb) — Masatoshi Seki <m_seki@...>
咳といいます。
[#21639] load() blocks thread scheduling — Tietew <tietew-ml-ruby-dev@...>
Tietew です。
まつもと ゆきひろです
[#21641] SOAP::StreamError: Illegal media type. — matz@... (Yukihiro Matsumoto)
まつもと ゆきひろです。
[#21679] Proposal: string literal concatenation — mput <root@...>
mput です。
[#21682] ruby-tk hangs when exception is raised — akira yamada <akira@...>
なかだです。
永井@知能.九工大です.
永井@知能.九工大です.
永井@知能.九工大です.
永井@知能.九工大です.
永井@知能.九工大です.
永井@知能.九工大です.
永井@知能.九工大です.
永井@知能.九工大です.
永井@知能.九工大です.
なかだです。
永井@知能.九工大です.
なかだです。
永井@知能.九工大です.
なかだです。
永井@知能.九工大です.
なかだです。
永井@知能.九工大です.
なかだです。
永井@知能.九工大です.
なかだです。
永井@知能.九工大です.
まつもと ゆきひろです
永井@知能.九工大です.
永井@知能.九工大です.
永井@知能.九工大です.
永井@知能.九工大です.
[#21707] drb Hash#each — matz@... (Yukihiro Matsumoto)
まつもと ゆきひろです
まつもと ゆきひろです
まつもと ゆきひろです
まつもと ゆきひろです
咳といいます。
まつもと ゆきひろです
まつもと ゆきひろです
まつもと ゆきひろです
[#21730] exit in $SAFE = 4 with -d — Tanaka Akira <akr@...17n.org>
% ruby -de 'lambda { $SAFE = 4; exit }.call; p 1'
[#21747] ruby 1.8.1 preview1 schedule — matz@... (Yukihiro Matsumoto)
関係者各位、
Siena. です。
なかだです。
Siena. です。
なかだです。
[#21778] IOError while building on Solaris with Sun cc — 桑村慎哉 <kuwa@...>
桑村です。
まつもと ゆきひろです
[#21790] ruby 1.8.1 preview1 — matz@... (Yukihiro Matsumoto)
It's out.
取り敢えず、NetBSD currentでの状況です。pkgsrc的なことは特にせず、ある
[#21794] ruby-1.8.1-preview2 での rb_iter_break — Kenta MURATA <muraken2@...>
むらけんです.
[ruby-dev:21568] Re: rewinding for Thread
なかだです。
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はできる。
中田 伸悦