[#21809] lib/test/unit/ui/tk/testrunner.rb — Kazuhiro NISHIYAMA <zn@...>
西山和広です。
永井@知能.九工大です.
なかだです。
永井@知能.九工大です.
なかだです。
永井@知能.九工大です.
なかだです。
こんにちは、なかむら(う)です。
永井@知能.九工大です.
なかだです。
永井@知能.九工大です.
[#21830] pty on FreeBSD — matz@... (Yukihiro Matsumoto)
まつもと ゆきひろです
[#21846] StringIO#path — matz@... (Yukihiro Matsumoto)
まつもと ゆきひろです
[#21876] get_last_error or getLastError by DL::Importable — Take_tk <ggb03124@...>
たけ(tk)です。
[#21883] right hand Regexp — Koji Arai <JCA02266@...>
新井です。
[#21899] core dump in rb_hash_aset — Tanaka Akira <akr@...17n.org>
% ruby -e 'h = {}
まつもと ゆきひろです
In article <1068753744.644627.6908.nullmailer@picachu.netlab.jp>,
[#21932] rough / tabs.rb — Minero Aoki <aamine@...>
青木です。
[#21939] StringIO.new("").read — Tanaka Akira <akr@...17n.org>
ふと気がついたのですが、
[#21942] Zlib::GzipReader#read — Tanaka Akira <akr@...17n.org>
ふと気がついたのですが、
[#21943] IO#read — Tanaka Akira <akr@...17n.org>
ふと。
In article <87u1523sjj.fsf@serein.a02.aist.go.jp>,
なかだです。
In article <200311250059.hAP0xSYw004490@sharui.nakada.kanuma.tochigi.jp>,
[#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@...>
こんにちは、なかむら(う)です。
Siena. です。
青木です。それにしても凄い Subject だ。
[#22000] purge pthread at configure — "U.Nakamura" <usa@...>
こんにちは、なかむら(う)です。
[#22013] HTTP_PROXY — Tanaka Akira <akr@...17n.org>
ふと
[#22025] --enable-pthread on FreeBSD — "U.Nakamura" <usa@...>
こんにちは、なかむら(う)です。
[#22042] ENV["path"].tainted? — Tanaka Akira <akr@...17n.org>
ENV["path"] の値が
まつもと ゆきひろです
In article <1069748137.095435.3356.nullmailer@picachu.netlab.jp>,
斜め読みですが、
まつもと ゆきひろです
In message <1070234162.951847.24883.nullmailer@picachu.netlab.jp>
[#22057] drb/drb.rb document — Minero Aoki <aamine@...>
青木です。
[#22071] Dir.glob と Shjift_JIS について — "H.Yamamoto" <ocean@...2.ccsnet.ne.jp>
はじめまして。山本といいます。
Siena. です。
> 山本さんのパッチがうまく当たらず手パッチしたので、念のため何度か
Siena. です。
こんにちは、山本です。
山本です。
山本です。
山本です。
山本です。glob_helperをリファクタリングしてみました。
なかだです。
山本です。
なかだです。
山本です。
Siena. です。
山本です。
山本です。
まつもと ゆきひろです
山本です。
山本です。パッチを送ります。
山本です。
山本です。
山本です。
山本です。
まつもと ゆきひろです
>すいません。パッチを出す時にはいつもどの時点のソースに対する
まつもと ゆきひろです
>|すみません、1.8.1に対してです。
まつもと ゆきひろです
こんにちは、山本です。
まつもと ゆきひろです
山本です。
山本です。
山本です。[ruby-dev:22470]にバグがあったので修正しました。
>山本です。[ruby-dev:22470]にバグがあったので修正しました。
まつもと ゆきひろです
山本です。
山本です。
In message <20040102230135.027CDAF8.ocean@m2.ccsnet.ne.jp>
山本です。
まつもと ゆきひろです
山本です。
山本です。
山本です。
なかだです。
山本です。
なかだです。
山本です。
[ruby-dev:21868] Re: lib/test/unit/ui/tk/testrunner.rb
永井@知能.九工大です.
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