[#21809] lib/test/unit/ui/tk/testrunner.rb — Kazuhiro NISHIYAMA <zn@...>

西山和広です。

23 messages 2003/11/01
[#21815] Re: lib/test/unit/ui/tk/testrunner.rb — Hidetoshi NAGAI <nagai@...> 2003/11/01

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

[#21858] Re: lib/test/unit/ui/tk/testrunner.rb — nobu.nakada@... 2003/11/06

なかだです。

[#21859] Re: lib/test/unit/ui/tk/testrunner.rb — Hidetoshi NAGAI <nagai@...> 2003/11/06

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

[#21860] Re: lib/test/unit/ui/tk/testrunner.rb — nobu.nakada@... 2003/11/06

なかだです。

[#21861] Re: lib/test/unit/ui/tk/testrunner.rb — Hidetoshi NAGAI <nagai@...> 2003/11/07

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

[#21862] Re: lib/test/unit/ui/tk/testrunner.rb — nobu.nakada@... 2003/11/07

なかだです。

[#21946] Re: [ruby-cvs] ruby, ruby/lib, ruby/test/fileutils: * lib/fileutils.rb (fu_same?): check by inode instead of path name, to detect two hard links pointing to the same content. — "U.Nakamura" <usa@...>

こんにちは、なかむら(う)です。

14 messages 2003/11/18
[#21972] Re: [ruby-cvs] ruby, ruby/lib, ruby/test/fileutils: * lib/fileutils.rb (fu_same?): check by inode instead of path name, to detect two hard links pointing to the same content. — siena@... (Siena. / SHINAGAWA, Norihide) 2003/11/19

Siena. です。

[#22013] HTTP_PROXY — Tanaka Akira <akr@...17n.org>

ふと

19 messages 2003/11/24

[#22042] ENV["path"].tainted? — Tanaka Akira <akr@...17n.org>

ENV["path"] の値が

14 messages 2003/11/25
[#22043] Re: ENV["path"].tainted? — matz@... (Yukihiro Matsumoto) 2003/11/25

まつもと ゆきひろです

[#22071] Dir.glob と Shjift_JIS について — "H.Yamamoto" <ocean@...2.ccsnet.ne.jp>

はじめまして。山本といいます。

119 messages 2003/11/28
[#22075] Re: Dir.glob と Shjift_JIS について — siena@... (Siena. / SHINAGAWA, Norihide) 2003/11/29

Siena. です。

[#22076] Re: Dir.glob と Shjift_JIS について — "H.Yamamoto" <ocean@...2.ccsnet.ne.jp> 2003/11/29

> 山本さんのパッチがうまく当たらず手パッチしたので、念のため何度か

[#22078] Re: Dir.glob と Shjift_JIS について — siena@... (Siena. / SHINAGAWA, Norihide) 2003/11/29

Siena. です。

[#22089] Re: Dir.glob と Shjift_JIS について — "H.Yamamoto" <ocean@...2.ccsnet.ne.jp> 2003/11/30

こんにちは、山本です。

[#22100] Re: Dir.glob と Shjift_JIS について — "H.Yamamoto" <ocean@...2.ccsnet.ne.jp> 2003/12/01

山本です。

[#22147] Re: Dir.glob と Shjift_JIS について — "H.Yamamoto" <ocean@...2.ccsnet.ne.jp> 2003/12/05

山本です。

[#22258] Re: Dir.glob と Shjift_JIS について — "H.Yamamoto" <ocean@...2.ccsnet.ne.jp> 2003/12/13

山本です。glob_helperをリファクタリングしてみました。

[#22263] Re: Dir.glob と Shjift_JIS について — nobu.nakada@... 2003/12/13

なかだです。

[#22267] Re: Dir.glob とShjift_JIS について — "H.Yamamoto" <ocean@...2.ccsnet.ne.jp> 2003/12/13

山本です。

[#22441] Re: Dir.glob と Shjift_JIS について — "H.Yamamoto" <ocean@...2.ccsnet.ne.jp> 2003/12/27

山本です。

[#22442] Re: Dir.glob と Shjift_JIS について — matz@... (Yukihiro Matsumoto) 2003/12/27

まつもと ゆきひろです

[#22443] Re: Dir.glob とShjift_JIS について — "H.Yamamoto" <ocean@...2.ccsnet.ne.jp> 2003/12/28

山本です。

[#22444] Re: Dir.glob とShjift_JIS について — "H.Yamamoto" <ocean@...2.ccsnet.ne.jp> 2003/12/28

山本です。パッチを送ります。

[#22445] Re: Dir.glob とShjift_JIS について — "H.Yamamoto" <ocean@...2.ccsnet.ne.jp> 2003/12/28

山本です。

[#22446] Re: Dir.glob とShjift_JIS について — "H.Yamamoto" <ocean@...2.ccsnet.ne.jp> 2003/12/28

山本です。

[#22447] Re: Dir.glob とShjift_JIS について — "H.Yamamoto" <ocean@...2.ccsnet.ne.jp> 2003/12/28

山本です。

[#22449] Re: Dir.glob とShjift_JIS について — "H.Yamamoto" <ocean@...2.ccsnet.ne.jp> 2003/12/29

山本です。

[#22451] Re: Dir.glob とShjift_JIS について — matz@... (Yukihiro Matsumoto) 2003/12/29

まつもと ゆきひろです

[#22452] Re: Dir.glob とShjift_JIS について — "H.Yamamoto" <ocean@...2.ccsnet.ne.jp> 2003/12/30

>すいません。パッチを出す時にはいつもどの時点のソースに対する

[#22453] Re: Dir.glob とShjift_JIS について — matz@... (Yukihiro Matsumoto) 2003/12/30

まつもと ゆきひろです

[#22454] Re: Dir.glob とShjift_JIS について — "H.Yamamoto" <ocean@...2.ccsnet.ne.jp> 2003/12/30

>|すみません、1.8.1に対してです。

[#22455] Re: Dir.glob とShjift_JIS について — matz@... (Yukihiro Matsumoto) 2003/12/30

まつもと ゆきひろです

[#22456] Re: Dir.glob とShjift_JIS について — "H.Yamamoto" <ocean@...2.ccsnet.ne.jp> 2003/12/30

こんにちは、山本です。

[#22457] Re: Dir.glob とShjift_JIS について — matz@... (Yukihiro Matsumoto) 2003/12/30

まつもと ゆきひろです

[#22470] Re: Dir.glob とShjift_JIS について — "H.Yamamoto" <ocean@...2.ccsnet.ne.jp> 2003/12/31

山本です。

[#22471] Re: Dir.glob とShjift_JIS について — "H.Yamamoto" <ocean@...2.ccsnet.ne.jp> 2004/01/01

山本です。

[#22476] Re: Dir.glob とShjift_JIS について — "H.Yamamoto" <ocean@...2.ccsnet.ne.jp> 2004/01/02

山本です。[ruby-dev:22470]にバグがあったので修正しました。

[#22477] Re: Dir.glob とShjift_JIS について — "H.Yamamoto" <ocean@...2.ccsnet.ne.jp> 2004/01/02

>山本です。[ruby-dev:22470]にバグがあったので修正しました。

[#22478] Re: Dir.glob とShjift_JIS について — matz@... (Yukihiro Matsumoto) 2004/01/02

まつもと ゆきひろです

[#22151] Re: Dir.glob と Shjift_JIS について — "H.Yamamoto" <ocean@...2.ccsnet.ne.jp> 2003/12/05

山本です。

[ruby-dev:21868] Re: lib/test/unit/ui/tk/testrunner.rb

From: Hidetoshi NAGAI <nagai@...>
Date: 2003-11-07 14:40:20 UTC
List: ruby-dev #21868
永井@知能.九工大です.

From: nobu.nakada@nifty.ne.jp
Subject: [ruby-dev:21867] Re: lib/test/unit/ui/tk/testrunner.rb
Date: Fri, 7 Nov 2003 20:55:37 +0900
Message-ID: <200311071155.hA7Btabd008906@sharui.nakada.kanuma.tochigi.jp>
> > 遅くなりましたが,これではどうでしょうか?
> --with-pthread-extあり/なしともに大丈夫そうです。

どうやら本質は下記 patch の修正にあるようですね.
--with-pthread-ext による対応は必要なさそうです.
--with-pthread-ext の commit はちょっと早まったかもしれませんね.

# 前回のはまだつまらないバグが残っておりました.ごめんなさい.

で,下記 patch を試してみていただいて,--with-pthread-ext の有無に
関係なく正常動作するとしたら,以前の commit 分はどうしましょう?

  1. あってもなくても一緒だったのだから,元通りに消してしまう.

  2. 今回は最終的にはこれによる効果はなかったが,一部の状況は救えて
     いたことから,状況次第ではこれで救えるケースもあるかもしれない
     ということでそのまま残しておく.

上記の結論と下記 patch の動作確認結果とがはっきりしてから
修正を commit することにします.
よろしくお願いします.

Index: tcltklib.c
===================================================================
RCS file: /src/ruby/ext/tcltklib/tcltklib.c,v
retrieving revision 1.45
diff -u -r1.45 tcltklib.c
--- tcltklib.c	29 Oct 2003 11:03:54 -0000	1.45
+++ tcltklib.c	7 Nov 2003 14:19:50 -0000
@@ -79,6 +79,16 @@
     VALUE *result;
     VALUE thread;
 };
+
+struct eval_queue {
+    Tcl_Event ev;
+    VALUE str;
+    VALUE obj;
+    int done;
+    int safe_level;
+    VALUE *result;
+    VALUE thread;
+};
  
 static VALUE eventloop_thread;
 static VALUE watchdog_thread;
@@ -451,7 +461,9 @@
 		    }
 		}
 
-		if (Tcl_DoOneEvent(TCL_ALL_EVENTS | TCL_DONT_WAIT)) {
+		found_event = Tcl_DoOneEvent(TCL_ALL_EVENTS | TCL_DONT_WAIT);
+
+		if (found_event) {
 		    tick_counter++;
 		} else {
 		    tick_counter += no_event_tick;
@@ -687,6 +699,7 @@
 {
     VALUE vflags;
     int flags;
+    int found_event;
 
     if (rb_scan_args(argc, argv, "01", &vflags) == 0) {
 	flags = TCL_ALL_EVENTS | TCL_DONT_WAIT;
@@ -708,7 +721,9 @@
 	}
     }
 
-    if (Tcl_DoOneEvent(flags)) {
+    found_event = Tcl_DoOneEvent(TCL_ALL_EVENTS | TCL_DONT_WAIT);
+
+    if (found_event) {
 	return Qtrue;
     } else {
 	return Qfalse;
@@ -736,7 +751,7 @@
 
 /* Tcl command `ruby' */
 static VALUE
-ip_eval_rescue(failed, einfo)
+ip_ruby_eval_rescue(failed, einfo)
     VALUE *failed;
     VALUE einfo;
 {
@@ -744,55 +759,28 @@
     return Qnil;
 }
 
-/* restart Tk */
+struct eval_body_arg {
+    char  *string;
+    VALUE failed;
+};
+
 static VALUE
-lib_restart(self)
-    VALUE self;
+ip_ruby_eval_body(arg)
+     struct eval_body_arg *arg;
 {
-    struct tcltkip *ptr = get_ip(self);
-
-    rb_secure(4);
-
-    /* destroy the root wdiget */
-    ptr->return_value = Tcl_Eval(ptr->ip, "destroy .");
-    /* ignore ERROR */
-    DUMP2("(TCL_Eval result) %d", ptr->return_value);
-
-    /* execute Tk_Init of Tk_SafeInit */
-#if TCL_MAJOR_VERSION >= 8
-    if (Tcl_IsSafe(ptr->ip)) {
-	DUMP1("Tk_SafeInit");
-	if (Tk_SafeInit(ptr->ip) == TCL_ERROR) {
-	    rb_raise(rb_eRuntimeError, "%s", ptr->ip->result);
-	}
-    } else {
-	DUMP1("Tk_Init");
-	if (Tk_Init(ptr->ip) == TCL_ERROR) {
-	    rb_raise(rb_eRuntimeError, "%s", ptr->ip->result);
-	}
-    }
-#else
-    DUMP1("Tk_Init");
-    if (Tk_Init(ptr->ip) == TCL_ERROR) {
-	rb_raise(rb_eRuntimeError, "%s", ptr->ip->result);
-    }
-#endif
-
-    return Qnil;
+    rb_trap_immediate = 0;
+    return rb_rescue2(rb_eval_string, (VALUE)arg->string, 
+		      ip_ruby_eval_rescue, (VALUE)&(arg->failed),
+		      rb_eStandardError, rb_eScriptError, rb_eSystemExit, 
+		      (VALUE)0);
 }
 
 static VALUE
-ip_restart(self)
-    VALUE self;
+ip_ruby_eval_ensure(trapflag)
+     VALUE trapflag;
 {
-    struct tcltkip *ptr = get_ip(self);
-
-    rb_secure(4);
-    if (Tcl_GetMaster(ptr->ip) != (Tcl_Interp*)NULL) {
-	/* slave IP */
-	return Qnil;
-    }
-    return lib_restart(self);
+    rb_trap_immediate = NUM2INT(trapflag);
+    return Qnil;
 }
 
 static int
@@ -811,9 +799,8 @@
 #endif
 {
     VALUE res;
-    int old_trapflg;
-    VALUE failed = 0;
-    char *arg;
+    int old_trapflag;
+     struct eval_body_arg arg;
     int  dummy;
 
     /* ruby command has 1 arg. */
@@ -823,34 +810,31 @@
 
     /* get C string from Tcl object */
 #if TCL_MAJOR_VERSION >= 8
-    arg = Tcl_GetStringFromObj(argv[1], &dummy);
+    arg.string = Tcl_GetStringFromObj(argv[1], &dummy);
 #else
-    arg = argv[1];
+    arg.string = argv[1];
 #endif
+    arg.failed = 0;
 
     /* evaluate the argument string by ruby */
     DUMP2("rb_eval_string(%s)", arg);
-    old_trapflg = rb_trap_immediate;
-    rb_trap_immediate = 0;
-    res = rb_rescue2(rb_eval_string, (VALUE)arg, 
-                     ip_eval_rescue, (VALUE)&failed,
-                     rb_eStandardError, rb_eScriptError, rb_eSystemExit, 
-		     (VALUE)0);
-    rb_trap_immediate = old_trapflg;
+    old_trapflag = rb_trap_immediate;
+    res = rb_ensure(ip_ruby_eval_body, (VALUE)&arg, 
+		    ip_ruby_eval_ensure, INT2FIX(old_trapflag));
 
     /* status check */
-    if (failed) {
-        VALUE eclass = CLASS_OF(failed);
+    if (arg.failed) {
+        VALUE eclass = CLASS_OF(arg.failed);
 	DUMP1("(rb_eval_string result) failed");
 	Tcl_ResetResult(interp);
-	Tcl_AppendResult(interp, StringValuePtr(failed), (char*)NULL);
+	Tcl_AppendResult(interp, StringValuePtr(arg.failed), (char*)NULL);
         if (eclass == eTkCallbackBreak) {
 	    return TCL_BREAK;
 	} else if (eclass == eTkCallbackContinue) {
 	    return TCL_CONTINUE;
 	} else if (eclass == rb_eSystemExit) {
 	    Tcl_Eval(interp, "destroy .");
-	    rb_raise(rb_eSystemExit, StringValuePtr(failed));
+	    rb_raise(rb_eSystemExit, StringValuePtr(arg.failed));
 	} else {
 	    return TCL_ERROR;
 	}
@@ -1743,9 +1727,10 @@
     }
 }
 
+
 /* eval string in tcl by Tcl_Eval() */
 static VALUE
-ip_eval(self, str)
+ip_eval_real(self, str)
     VALUE self;
     VALUE str;
 {
@@ -1767,6 +1752,179 @@
     /* pass back the result (as string) */
     /* return(rb_str_new2(ptr->ip->result)); */
     return(rb_tainted_str_new2(ptr->ip->result));
+}
+
+static VALUE
+evq_safelevel_handler(arg, evq)
+    VALUE arg;
+    VALUE evq;
+{
+    struct eval_queue *q;
+
+    Data_Get_Struct(evq, struct eval_queue, q);
+    DUMP2("(safe-level handler) $SAFE = %d", q->safe_level);
+    rb_set_safe_level(q->safe_level);
+    return ip_eval_real(q->obj, q->str);
+}
+
+int eval_queue_handler _((Tcl_Event *, int));
+int
+eval_queue_handler(evPtr, flags)
+    Tcl_Event *evPtr;
+    int flags;
+{
+    struct eval_queue *q = (struct eval_queue *)evPtr;
+
+    DUMP2("do_eval_queue_handler : evPtr = %lx", evPtr);
+    DUMP2("eval queue_thread : %lx", rb_thread_current());
+    DUMP2("added by thread : %lx", q->thread);
+
+    if (q->done) {
+	DUMP1("processed by another event-loop");
+	return 0;
+    } else {
+	DUMP1("process it on current event-loop");
+    }
+
+    /* process it */
+    q->done = 1;
+
+    /* check safe-level */
+    if (rb_safe_level() != q->safe_level) {
+	*(q->result) 
+	    = rb_funcall(rb_proc_new(evq_safelevel_handler, 
+				     Data_Wrap_Struct(rb_cData,0,0,q)), 
+			 rb_intern("call"), 0);
+    } else {
+    DUMP2("call eval_real (for caller thread:%lx)", q->thread);
+    DUMP2("call eval_real (current thread:%lx)", rb_thread_current());
+	*(q->result) = ip_eval_real(q->obj, q->str);
+    }
+
+    /* back to caller */
+    DUMP2("back to caller (caller thread:%lx)", q->thread);
+    DUMP2("               (current thread:%lx)", rb_thread_current());
+    rb_thread_run(q->thread);
+    DUMP1("finish back to caller");
+
+    /* end of handler : remove it */
+    return 1;
+}
+
+static VALUE
+ip_eval(self, str)
+    VALUE self;
+    VALUE str;
+{
+    struct eval_queue *tmp;
+    VALUE current = rb_thread_current();
+    VALUE result;
+    VALUE *alloc_result;
+    Tcl_QueuePosition position;
+
+    if (eventloop_thread == 0 || current == eventloop_thread) {
+	if (eventloop_thread) {
+	    DUMP2("eval from current eventloop %lx", current);
+	} else {
+	    DUMP2("eval from thread:%lx but no eventloop", current);
+	}
+	result = ip_eval_real(self, str);
+	if (rb_obj_is_kind_of(result, rb_eException)) {
+	    rb_exc_raise(result);
+	}
+	return result;
+    }
+
+    DUMP2("eval from thread %lx (NOT current eventloop)", current);
+
+    /* allocate memory (protected from Tcl_ServiceEvent) */
+    alloc_result = ALLOC(VALUE);
+
+    /* allocate memory (freed by Tcl_ServiceEvent) */
+    tmp = (struct eval_queue *)Tcl_Alloc(sizeof(struct eval_queue));
+
+    /* construct event data */
+    tmp->done = 0;
+    tmp->obj = self;
+    tmp->str = str;
+    tmp->result = alloc_result;
+    tmp->thread = current;
+    tmp->safe_level = rb_safe_level();
+    tmp->ev.proc = eval_queue_handler;
+    position = TCL_QUEUE_TAIL;
+
+    /* add the handler to Tcl event queue */
+    DUMP1("add handler");
+    Tcl_QueueEvent(&(tmp->ev), position);
+
+    /* wait for the handler to be processed */
+    DUMP2("wait for handler (current thread:%lx)", current);
+    rb_thread_stop();
+    DUMP2("back from handler (current thread:%lx)", current);
+
+    /* get result & free allocated memory */
+    result = *alloc_result;
+    free(alloc_result);
+    if (rb_obj_is_kind_of(result, rb_eException)) {
+	rb_exc_raise(result);
+    }
+
+    return result;
+}
+
+
+/* restart Tk */
+static VALUE
+lib_restart(self)
+    VALUE self;
+{
+    struct tcltkip *ptr = get_ip(self);
+
+    rb_secure(4);
+
+    /* destroy the root wdiget */
+    /* ptr->return_value = Tcl_Eval(ptr->ip, "destroy ."); */
+    ptr->return_value = FIX2INT(ip_eval(self, "destroy ."));
+    /* ignore ERROR */
+    DUMP2("(TCL_Eval result) %d", ptr->return_value);
+    Tcl_ResetResult(ptr->ip);
+
+    /* execute Tk_Init of Tk_SafeInit */
+#if TCL_MAJOR_VERSION >= 8
+    if (Tcl_IsSafe(ptr->ip)) {
+	DUMP1("Tk_SafeInit");
+	if (Tk_SafeInit(ptr->ip) == TCL_ERROR) {
+	    rb_raise(rb_eRuntimeError, "%s", ptr->ip->result);
+	}
+    } else {
+	DUMP1("Tk_Init");
+	if (Tk_Init(ptr->ip) == TCL_ERROR) {
+	    rb_raise(rb_eRuntimeError, "%s", ptr->ip->result);
+	}
+    }
+#else
+    DUMP1("Tk_Init");
+    if (Tk_Init(ptr->ip) == TCL_ERROR) {
+	rb_raise(rb_eRuntimeError, "%s", ptr->ip->result);
+    }
+#endif
+
+    return Qnil;
+}
+
+
+static VALUE
+ip_restart(self)
+    VALUE self;
+{
+    struct tcltkip *ptr = get_ip(self);
+
+    rb_secure(4);
+    if (Tcl_GetMaster(ptr->ip) != (Tcl_Interp*)NULL) {
+	/* slave IP */
+	return Qnil;
+    }
+    return lib_restart(self);
 }
 
 static VALUE

-- 
                                         永井 秀利 (九工大 知能情報)
                                             nagai@ai.kyutech.ac.jp

In This Thread