永井@知能.九工大です. From: Yukihiro Matsumoto <matz / ruby-lang.org> Subject: [ruby-dev:27922] Re: 1.8.4 Preview2 検証 Date: Fri, 2 Dec 2005 00:25:43 +0900 Message-ID: <1133450737.002429.4354.nullmailer / x31.priv.netlab.jp> > はい、あらかじめ宣言してあるRuby/Tkの新バージョン対応以外は > 仕様変更は単純な追加も含めて「原則として」禁止です。バグフィッ > クス以外のコミットは行わないでください。 Ruby/Tk に関してですが,現在 Tcl/Tk は 8.4.12rc2 です. これまでのところ,対応が必要と思われる変更は見当たりませんので, 8.4.12 のリリース版でも大丈夫だと思います. なお,添付の diff は,次のバグを修正するためのものです. --------------------------------------------------------------------- ・vwait や tkwait 時に,対象となっている Tk インタープリタが delete されたにもかかわらず,vwait や tkwait の待ちを 抜け出せない恐れがある. ・vwait や tkwait 時に,スレッド切り替えや割込み処理ができなくなる. --------------------------------------------------------------------- コミットしても構わないでしょうか? -- 永井 秀利 (九工大 知能情報) nagai / ai.kyutech.ac.jp --- tcltklib.c.old 2005-11-18 16:17:37.000000000 +0900 +++ tcltklib.c 2005-12-04 12:20:33.000000000 +0900 @@ -1271,10 +1271,11 @@ static int -lib_eventloop_core(check_root, update_flag, check_var) +lib_eventloop_core(check_root, update_flag, check_var, interp) int check_root; int update_flag; int *check_var; + Tcl_Interp *interp; { volatile VALUE current = eventloop_thread; int found_event = 1; @@ -1324,6 +1325,11 @@ if (*check_var || !found_event) { return found_event; } + if (interp != (Tcl_Interp*)NULL + && Tcl_InterpDeleted(interp)) { + /* IP for check_var is deleted */ + return 0; + } } /* found_event = Tcl_DoOneEvent(event_flag); */ @@ -1435,6 +1441,11 @@ if (*check_var || !found_event) { return found_event; } + if (interp != (Tcl_Interp*)NULL + && Tcl_InterpDeleted(interp)) { + /* IP for check_var is deleted */ + return 0; + } } if (NIL_P(eventloop_thread) || current == eventloop_thread) { @@ -1611,6 +1622,8 @@ int check_root; int update_flag; int *check_var; + Tcl_Interp *interp; + int thr_crit_bup; }; VALUE @@ -1623,7 +1636,8 @@ if (lib_eventloop_core(params->check_root, params->update_flag, - params->check_var)) { + params->check_var, + params->interp)) { return Qtrue; } else { return Qfalse; @@ -1676,6 +1690,9 @@ DUMP2("eventloop_ensure: eventloop-thread : %lx", eventloop_thread); if (eventloop_thread != current_evloop) { DUMP2("finish eventloop %lx (NOT current eventloop)", current_evloop); + + rb_thread_critical = ptr->thr_crit_bup; + return Qnil; } @@ -1706,15 +1723,18 @@ free(ptr); + rb_thread_critical = ptr->thr_crit_bup; + DUMP2("finish current eventloop %lx", current_evloop); return Qnil; } static VALUE -lib_eventloop_launcher(check_root, update_flag, check_var) +lib_eventloop_launcher(check_root, update_flag, check_var, interp) int check_root; int update_flag; int *check_var; + Tcl_Interp *interp; { volatile VALUE parent_evloop = eventloop_thread; struct evloop_params *args = ALLOC(struct evloop_params); @@ -1742,9 +1762,13 @@ DUMP3("tcltklib: eventloop-thread : %lx -> %lx\n", parent_evloop, eventloop_thread); - args->check_root = check_root; - args->update_flag = update_flag; - args->check_var = check_var; + args->check_root = check_root; + args->update_flag = update_flag; + args->check_var = check_var; + args->interp = interp; + args->thr_crit_bup = rb_thread_critical; + + rb_thread_critical = Qfalse; #if 0 return rb_ensure(lib_eventloop_main, (VALUE)args, @@ -1771,7 +1795,8 @@ check_rootwidget = Qfalse; } - return lib_eventloop_launcher(RTEST(check_rootwidget), 0, (int*)NULL); + return lib_eventloop_launcher(RTEST(check_rootwidget), 0, + (int*)NULL, (Tcl_Interp*)NULL); } static VALUE @@ -1799,7 +1824,8 @@ watchdog_evloop_launcher(check_rootwidget) VALUE check_rootwidget; { - return lib_eventloop_launcher(RTEST(check_rootwidget), 0, (int*)NULL); + return lib_eventloop_launcher(RTEST(check_rootwidget), 0, + (int*)NULL, (Tcl_Interp*)NULL); } #define EVLOOP_WAKEUP_CHANCE 3 @@ -1981,8 +2007,8 @@ rb_thread_schedule(); /* start sub-eventloop */ - foundEvent = lib_eventloop_launcher(/* not check root-widget */0, 0, - q->done); + foundEvent = RTEST(lib_eventloop_launcher(/* not check root-widget */0, 0, + q->done, (Tcl_Interp*)NULL)); if (RTEST(rb_funcall(th, ID_alive_p, 0))) { rb_funcall(th, ID_kill, 0); @@ -2812,7 +2838,7 @@ /* call eventloop */ /* ret = lib_eventloop_core(0, flags, (int *)NULL);*/ /* ignore result */ - ret = lib_eventloop_launcher(0, flags, (int *)NULL); /* ignore result */ + ret = RTEST(lib_eventloop_launcher(0, flags, (int *)NULL, interp)); /* ignore result */ /* exception check */ if (!NIL_P(rbtk_pending_exception)) { @@ -2995,6 +3021,24 @@ /* replace of vwait/tkwait */ /***************************/ #if TCL_MAJOR_VERSION >= 8 +static int ip_rbVwaitObjCmd _((ClientData, Tcl_Interp *, int, + Tcl_Obj *CONST [])); +static int ip_rb_threadVwaitObjCmd _((ClientData, Tcl_Interp *, int, + Tcl_Obj *CONST [])); +static int ip_rbTkWaitObjCmd _((ClientData, Tcl_Interp *, int, + Tcl_Obj *CONST [])); +static int ip_rb_threadTkWaitObjCmd _((ClientData, Tcl_Interp *, int, + Tcl_Obj *CONST [])); +#else +static int ip_rbVwaitCommand _((ClientData, Tcl_Interp *, int, char *[])); +static int ip_rb_threadVwaitCommand _((ClientData, Tcl_Interp *, int, + char *[])); +static int ip_rbTkWaitCommand _((ClientData, Tcl_Interp *, int, char *[])); +static int ip_rb_threadTkWaitCommand _((ClientData, Tcl_Interp *, int, + char *[])); +#endif + +#if TCL_MAJOR_VERSION >= 8 static char *VwaitVarProc _((ClientData, Tcl_Interp *, CONST84 char *,CONST84 char *, int)); static char * @@ -3021,10 +3065,7 @@ return (char *) NULL; } - #if TCL_MAJOR_VERSION >= 8 -static int ip_rbVwaitObjCmd _((ClientData, Tcl_Interp *, int, - Tcl_Obj *CONST [])); static int ip_rbVwaitObjCmd(clientData, interp, objc, objv) ClientData clientData; @@ -3032,7 +3073,6 @@ int objc; Tcl_Obj *CONST objv[]; #else /* TCL_MAJOR_VERSION < 8 */ -static int ip_rbVwaitCommand _((ClientData, Tcl_Interp *, int, char *[])); static int ip_rbVwaitCommand(clientData, interp, objc, objv) ClientData clientData; @@ -3053,6 +3093,20 @@ return TCL_ERROR; } +#if 0 + if (!rb_thread_alone() + && eventloop_thread != Qnil + && eventloop_thread != rb_thread_current()) { +#if TCL_MAJOR_VERSION >= 8 + DUMP1("call ip_rb_threadVwaitObjCmd"); + return ip_rb_threadVwaitObjCmd(clientData, interp, objc, objv); +#else /* TCL_MAJOR_VERSION < 8 */ + DUMP1("call ip_rb_threadVwaitCommand"); + return ip_rb_threadVwaitCommand(clientData, interp, objc, objv); +#endif + } +#endif + Tcl_Preserve(interp); #ifdef HAVE_NATIVETHREAD if (!is_ruby_native_thread()) { @@ -3117,8 +3171,8 @@ done = 0; - foundEvent - = lib_eventloop_launcher(/* not check root-widget */0, 0, &done); + foundEvent = RTEST(lib_eventloop_launcher(/* not check root-widget */0, + 0, &done, interp)); thr_crit_bup = rb_thread_critical; rb_thread_critical = Qtrue; @@ -3248,8 +3302,6 @@ } #if TCL_MAJOR_VERSION >= 8 -static int ip_rbTkWaitObjCmd _((ClientData, Tcl_Interp *, int, - Tcl_Obj *CONST [])); static int ip_rbTkWaitObjCmd(clientData, interp, objc, objv) ClientData clientData; @@ -3257,7 +3309,6 @@ int objc; Tcl_Obj *CONST objv[]; #else /* TCL_MAJOR_VERSION < 8 */ -static int ip_rbTkWaitCommand _((ClientData, Tcl_Interp *, int, char *[])); static int ip_rbTkWaitCommand(clientData, interp, objc, objv) ClientData clientData; @@ -3283,6 +3334,20 @@ return TCL_ERROR; } +#if 0 + if (!rb_thread_alone() + && eventloop_thread != Qnil + && eventloop_thread != rb_thread_current()) { +#if TCL_MAJOR_VERSION >= 8 + DUMP1("call ip_rb_threadTkWaitObjCmd"); + return ip_rb_threadTkWaitObjCmd(clientData, interp, objc, objv); +#else /* TCL_MAJOR_VERSION < 8 */ + DUMP1("call ip_rb_threadTkWaitCommand"); + return ip_rb_threadTkWwaitCommand(clientData, interp, objc, objv); +#endif + } +#endif + Tcl_Preserve(interp); if (objc != 3) { @@ -3394,7 +3459,7 @@ done = 0; /* lib_eventloop_core(check_rootwidget_flag, 0, &done); */ - lib_eventloop_launcher(check_rootwidget_flag, 0, &done); + lib_eventloop_launcher(check_rootwidget_flag, 0, &done, interp); thr_crit_bup = rb_thread_critical; rb_thread_critical = Qtrue; @@ -3463,7 +3528,7 @@ done = 0; /* lib_eventloop_core(check_rootwidget_flag, 0, &done); */ - lib_eventloop_launcher(check_rootwidget_flag, 0, &done); + lib_eventloop_launcher(check_rootwidget_flag, 0, &done, interp); /* exception check */ if (!NIL_P(rbtk_pending_exception)) { @@ -3560,7 +3625,7 @@ done = 0; /* lib_eventloop_core(check_rootwidget_flag, 0, &done); */ - lib_eventloop_launcher(check_rootwidget_flag, 0, &done); + lib_eventloop_launcher(check_rootwidget_flag, 0, &done, interp); /* exception check */ if (!NIL_P(rbtk_pending_exception)) { @@ -3678,8 +3743,6 @@ } #if TCL_MAJOR_VERSION >= 8 -static int ip_rb_threadVwaitObjCmd _((ClientData, Tcl_Interp *, int, - Tcl_Obj *CONST [])); static int ip_rb_threadVwaitObjCmd(clientData, interp, objc, objv) ClientData clientData; @@ -3687,8 +3750,6 @@ int objc; Tcl_Obj *CONST objv[]; #else /* TCL_MAJOR_VERSION < 8 */ -static int ip_rb_threadVwaitCommand _((ClientData, Tcl_Interp *, int, - char *[])); static int ip_rb_threadVwaitCommand(clientData, interp, objc, objv) ClientData clientData; @@ -3811,8 +3872,6 @@ } #if TCL_MAJOR_VERSION >= 8 -static int ip_rb_threadTkWaitObjCmd _((ClientData, Tcl_Interp *, int, - Tcl_Obj *CONST [])); static int ip_rb_threadTkWaitObjCmd(clientData, interp, objc, objv) ClientData clientData; @@ -3820,8 +3879,6 @@ int objc; Tcl_Obj *CONST objv[]; #else /* TCL_MAJOR_VERSION < 8 */ -static int ip_rb_threadTkWaitCommand _((ClientData, Tcl_Interp *, int, - char *[])); static int ip_rb_threadTkWaitCommand(clientData, interp, objc, objv) ClientData clientData;