From: Hidetoshi NAGAI Date: 2005-01-28T16:33:01+09:00 Subject: [ruby-dev:25585] Re: some problems on ext/tk/sample/**/*.rb 永井@知能.九工大です. From: Hidetoshi NAGAI Subject: [ruby-dev:25578] Re: some problems on ext/tk/sample/**/*.rb Date: Fri, 28 Jan 2005 12:16:58 +0900 Message-ID: <20050128.121645.74737034.nagai@ai.kyutech.ac.jp> > > 問題は「なぜ bcc32 では namespace が変化するのか」ですが・・・ > > スレッド切り替えのタイミングということなのかもしれませんが, > わからないですね. > たまたま bcc32 では発生しやすいだけという可能性もあります. > > とはいえ,これまで生じていた SEGV のかなりの部分の理由が > 判明したということで,とりあえずはほっとしています. 関数呼び出しをするとスレッド切り替えが発生して namespace が破壊される危険が高まる可能性があると考え, チェックをマクロで定義するようにしたパッチです. 問題がなければこれを今回の問題に対する修正の最終版として commit したいと思います. diff -urN --exclude=CVS tk.orig3/lib/multi-tk.rb tk/lib/multi-tk.rb --- tk.orig3/lib/multi-tk.rb 2005-01-25 13:10:40.000000000 +0900 +++ tk/lib/multi-tk.rb 2005-01-28 12:24:21.000000000 +0900 @@ -1568,8 +1568,8 @@ __getip.deleted? end - def null_namespace? - __getip.null_namespace? + def invalid_namespace? + __getip.invalid_namespace? end def abort(msg = nil) @@ -1894,8 +1894,8 @@ @interp.deleted? end - def null_namespace? - @interp.null_namespace? + def invalid_namespace? + @interp.invalid_namespace? end def abort(msg = nil) diff -urN --exclude=CVS tk.orig3/lib/remote-tk.rb tk/lib/remote-tk.rb --- tk.orig3/lib/remote-tk.rb 2005-01-25 13:10:54.000000000 +0900 +++ tk/lib/remote-tk.rb 2005-01-28 12:24:29.000000000 +0900 @@ -282,7 +282,7 @@ end end - def null_namespace? + def invalid_namespace? false end diff -urN --exclude=CVS tk.orig3/lib/tk.rb tk/lib/tk.rb --- tk.orig3/lib/tk.rb 2005-01-25 14:09:18.000000000 +0900 +++ tk/lib/tk.rb 2005-01-28 14:16:38.000000000 +0900 @@ -3940,7 +3940,7 @@ #Tk.freeze module Tk - RELEASE_DATE = '2005-01-25'.freeze + RELEASE_DATE = '2005-01-28'.freeze autoload :AUTO_PATH, 'tk/variable' autoload :TCL_PACKAGE_PATH, 'tk/variable' diff -urN --exclude=CVS tk.orig3/tcltklib.c tk/tcltklib.c --- tk.orig3/tcltklib.c 2005-01-28 11:21:52.000000000 +0900 +++ tk/tcltklib.c 2005-01-28 16:04:13.000000000 +0900 @@ -4,7 +4,7 @@ * Oct. 24, 1997 Y. Matsumoto */ -#define TCLTKLIB_RELEASE_DATE "2005-01-27" +#define TCLTKLIB_RELEASE_DATE "2005-01-28" #include "ruby.h" #include "rubysig.h" @@ -204,15 +204,17 @@ static int ip_ruby_cmd _((ClientData, Tcl_Interp *, int, char **)); #endif -static int ip_null_namespace _((Tcl_Interp *)); - #if TCL_MAJOR_VERSION == 8 && TCL_MINOR_VERSION < 5 +/* Tcl7.x doesn't have namespace support. */ +/* Tcl8.5+ has definition of Tcl_GetCurrentNamespace() in tclDecls.h */ # ifndef Tcl_GetCurrentNamespace EXTERN Tcl_Namespace * Tcl_GetCurrentNamespace _((Tcl_Interp *)); # endif # if defined(USE_TCL_STUBS) && !defined(USE_TCL_STUB_PROCS) # ifndef Tcl_GetCurrentNamespace -#define FunctionNum_of_GetCurrentNamespace 124 +# ifndef FunctionNum_of_GetCurrentNamespace +# define FunctionNum_of_GetCurrentNamespace 124 +# endif struct DummyTclIntStubs { int magic; struct TclIntStubHooks *hooks; @@ -251,6 +253,25 @@ return ptr; } + +/* namespace check */ +/* ip_null_namespace(Tcl_Interp *interp) */ +#if TCL_MAJOR_VERSION < 8 +#define ip_null_namespace(interp) (0) +#else /* support namespace */ +#define ip_null_namespace(interp) \ + (Tcl_GetCurrentNamespace(interp) == (Tcl_Namespace *)NULL) +#endif + +/* rbtk_invalid_namespace(tcltkip *ptr) */ +#if TCL_MAJOR_VERSION < 8 +#define rbtk_invalid_namespace(ptr) (0) +#else /* support namespace */ +#define rbtk_invalid_namespace(ptr) \ + ((ptr)->default_ns == (Tcl_Namespace*)NULL || Tcl_GetCurrentNamespace((ptr)->ip) != (ptr)->default_ns) +#endif + + /* increment/decrement reference count of tcltkip */ static int rbtk_preserve_ip(ptr) @@ -3402,9 +3423,7 @@ DUMP2("IP ref_count = %d", ptr->ref_count); - if (!Tcl_InterpDeleted(ptr->ip) && - !ip_null_namespace(ptr->ip) && - Tcl_GetCurrentNamespace(ptr->ip) == ptr->default_ns) { + if (!Tcl_InterpDeleted(ptr->ip) && !rbtk_invalid_namespace(ptr)) { DUMP2("IP(%lx) is not deleted", ptr->ip); /* Tcl_Preserve(ptr->ip); */ rbtk_preserve_ip(ptr); @@ -3413,20 +3432,16 @@ Tcl_ResetResult(ptr->ip); - if (!Tcl_InterpDeleted(ptr->ip) && !ip_null_namespace(ptr->ip) && - Tcl_GetCurrentNamespace(ptr->ip) == ptr->default_ns && - Tcl_GetCommandInfo(ptr->ip, finalize_hook_name, &info)) { + if (!Tcl_InterpDeleted(ptr->ip) && !rbtk_invalid_namespace(ptr) + && Tcl_GetCommandInfo(ptr->ip, finalize_hook_name, &info)) { DUMP2("call finalize hook proc '%s'", finalize_hook_name); Tcl_Eval(ptr->ip, finalize_hook_name); } - if (!Tcl_InterpDeleted(ptr->ip) && - Tcl_GetCurrentNamespace(ptr->ip) == ptr->default_ns && - Tcl_Eval(ptr->ip, DEF_CANCEL_AFTER_SCRIPTS_PROC) == TCL_OK) { - if (!Tcl_InterpDeleted(ptr->ip) && - !ip_null_namespace(ptr->ip) && - Tcl_GetCurrentNamespace(ptr->ip) == ptr->default_ns && - Tcl_GetCommandInfo(ptr->ip, CANCEL_AFTER_SCRIPTS, &info)) { + if (!Tcl_InterpDeleted(ptr->ip) && !rbtk_invalid_namespace(ptr) + && Tcl_Eval(ptr->ip, DEF_CANCEL_AFTER_SCRIPTS_PROC) == TCL_OK) { + if (!Tcl_InterpDeleted(ptr->ip) && !rbtk_invalid_namespace(ptr) + && Tcl_GetCommandInfo(ptr->ip, CANCEL_AFTER_SCRIPTS, &info)) { DUMP2("call cancel after scripts proc '%s'", CANCEL_AFTER_SCRIPTS); Tcl_Eval(ptr->ip, CANCEL_AFTER_SCRIPTS); @@ -3497,8 +3512,13 @@ rb_raise(rb_eRuntimeError, "fail to create a new Tk interpreter"); } +#if TCL_MAJOR_VERSION >= 8 DUMP1("get current namespace"); - ptr->default_ns = Tcl_GetCurrentNamespace(ptr->ip); + if ((ptr->default_ns = Tcl_GetCurrentNamespace(ptr->ip)) + == (Tcl_Namespace*)NULL) { + rb_raise(rb_eRuntimeError, "a new Tk interpreter has a NULL namespace"); + } +#endif rbtk_preserve_ip(ptr); DUMP2("IP ref_count = %d", ptr->ref_count); @@ -3741,7 +3761,9 @@ rb_thread_critical = thr_crit_bup; rb_raise(rb_eRuntimeError, "fail to create the new slave interpreter"); } +#if TCL_MAJOR_VERSION >= 8 slave->default_ns = Tcl_GetCurrentNamespace(slave->ip); +#endif rbtk_preserve_ip(slave); slave->has_orig_exit @@ -3909,19 +3931,16 @@ delete_slaves(ptr->ip); DUMP1("finalize operation"); - if (!Tcl_InterpDeleted(ptr->ip) && !ip_null_namespace(ptr->ip) && - Tcl_GetCurrentNamespace(ptr->ip) == ptr->default_ns && - Tcl_GetCommandInfo(ptr->ip, finalize_hook_name, &info)) { + if (!Tcl_InterpDeleted(ptr->ip) && !rbtk_invalid_namespace(ptr) + && Tcl_GetCommandInfo(ptr->ip, finalize_hook_name, &info)) { DUMP2("call finalize hook proc '%s'", finalize_hook_name); Tcl_Eval(ptr->ip, finalize_hook_name); } - if (!Tcl_InterpDeleted(ptr->ip) && - Tcl_GetCurrentNamespace(ptr->ip) == ptr->default_ns && - Tcl_Eval(ptr->ip, DEF_CANCEL_AFTER_SCRIPTS_PROC) == TCL_OK) { - if (!Tcl_InterpDeleted(ptr->ip) && !ip_null_namespace(ptr->ip) && - Tcl_GetCurrentNamespace(ptr->ip) == ptr->default_ns && - Tcl_GetCommandInfo(ptr->ip, CANCEL_AFTER_SCRIPTS, &info)) { + if (!Tcl_InterpDeleted(ptr->ip) && !rbtk_invalid_namespace(ptr) + && Tcl_Eval(ptr->ip, DEF_CANCEL_AFTER_SCRIPTS_PROC) == TCL_OK) { + if (!Tcl_InterpDeleted(ptr->ip) && !rbtk_invalid_namespace(ptr) + && Tcl_GetCommandInfo(ptr->ip, CANCEL_AFTER_SCRIPTS, &info)) { DUMP2("call cancel after scripts proc '%s'", CANCEL_AFTER_SCRIPTS); Tcl_Eval(ptr->ip, CANCEL_AFTER_SCRIPTS); @@ -3944,25 +3963,13 @@ } /* is deleted? */ -static int -ip_null_namespace(interp) - Tcl_Interp *interp; -{ -#if TCL_MAJOR_VERSION < 8 - return 0; -#else /* support Namespace */ - DUMP2("current namespace %lx",Tcl_GetCurrentNamespace(interp)); - return ( Tcl_GetCurrentNamespace(interp) == (Tcl_Namespace *)NULL ); -#endif -} - static VALUE -ip_has_null_namespace_p(self) +ip_has_invalid_namespace_p(self) VALUE self; { struct tcltkip *ptr = get_ip(self); - if (ip_null_namespace(ptr->ip)) { + if (rbtk_invalid_namespace(ptr)) { return Qtrue; } else { return Qfalse; @@ -3975,7 +3982,7 @@ { struct tcltkip *ptr = get_ip(self); - if (Tcl_InterpDeleted(ptr->ip)) { + if (Tcl_InterpDeleted(ptr->ip) || rbtk_invalid_namespace(ptr)) { return Qtrue; } else { return Qfalse; @@ -4091,8 +4098,7 @@ Tcl_IncrRefCount(cmd); /* ip is deleted? */ - if (Tcl_InterpDeleted(ptr->ip) || ip_null_namespace(ptr->ip) - || Tcl_GetCurrentNamespace(ptr->ip) != ptr->default_ns) { + if (Tcl_InterpDeleted(ptr->ip) || rbtk_invalid_namespace(ptr)) { DUMP1("ip is deleted"); Tcl_DecrRefCount(cmd); rb_thread_critical = thr_crit_bup; @@ -4133,8 +4139,7 @@ DUMP2("Tcl_Eval(%s)", cmd_str); /* ip is deleted? */ - if (Tcl_InterpDeleted(ptr->ip) || ip_null_namespace(ptr->ip) - || Tcl_GetCurrentNamespace(ptr->ip) != ptr->default_ns) { + if (Tcl_InterpDeleted(ptr->ip) || rbtk_invalid_namespace(ptr)) { DUMP1("ip is deleted"); ptr->return_value = TCL_OK; return rb_tainted_str_new2(""); @@ -4339,8 +4344,7 @@ rb_secure(4); /* ip is deleted? */ - if (Tcl_InterpDeleted(ptr->ip) || ip_null_namespace(ptr->ip) - || Tcl_GetCurrentNamespace(ptr->ip) != ptr->default_ns) { + if (Tcl_InterpDeleted(ptr->ip) || rbtk_invalid_namespace(ptr)) { DUMP1("ip is deleted"); rb_raise(rb_eRuntimeError, "interpreter is deleted"); } @@ -4829,8 +4833,7 @@ ptr = get_ip(interp); /* ip is deleted? */ - if (Tcl_InterpDeleted(ptr->ip) || ip_null_namespace(ptr->ip) - || Tcl_GetCurrentNamespace(ptr->ip) != ptr->default_ns) { + if (Tcl_InterpDeleted(ptr->ip) || rbtk_invalid_namespace(ptr)) { DUMP1("ip is deleted"); return rb_tainted_str_new2(""); } @@ -5312,8 +5315,7 @@ Tcl_IncrRefCount(nameobj); /* ip is deleted? */ - if (Tcl_InterpDeleted(ptr->ip) || ip_null_namespace(ptr->ip) - || Tcl_GetCurrentNamespace(ptr->ip) != ptr->default_ns) { + if (Tcl_InterpDeleted(ptr->ip) || rbtk_invalid_namespace(ptr)) { DUMP1("ip is deleted"); Tcl_DecrRefCount(nameobj); rb_thread_critical = thr_crit_bup; @@ -5377,8 +5379,7 @@ char *ret; /* ip is deleted? */ - if (Tcl_InterpDeleted(ptr->ip) || ip_null_namespace(ptr->ip) - || Tcl_GetCurrentNamespace(ptr->ip) != ptr->default_ns) { + if (Tcl_InterpDeleted(ptr->ip) || rbtk_invalid_namespace(ptr)) { DUMP1("ip is deleted"); return rb_tainted_str_new2(""); } else { @@ -5450,8 +5451,7 @@ Tcl_IncrRefCount(idxobj); /* ip is deleted? */ - if (Tcl_InterpDeleted(ptr->ip) || ip_null_namespace(ptr->ip) - || Tcl_GetCurrentNamespace(ptr->ip) != ptr->default_ns) { + if (Tcl_InterpDeleted(ptr->ip) || rbtk_invalid_namespace(ptr)) { DUMP1("ip is deleted"); Tcl_DecrRefCount(nameobj); Tcl_DecrRefCount(idxobj); @@ -5516,8 +5516,7 @@ char *ret; /* ip is deleted? */ - if (Tcl_InterpDeleted(ptr->ip) || ip_null_namespace(ptr->ip) - || Tcl_GetCurrentNamespace(ptr->ip) != ptr->default_ns) { + if (Tcl_InterpDeleted(ptr->ip) || rbtk_invalid_namespace(ptr)) { DUMP1("ip is deleted"); return rb_tainted_str_new2(""); } else { @@ -5614,8 +5613,7 @@ # endif /* ip is deleted? */ - if (Tcl_InterpDeleted(ptr->ip) || ip_null_namespace(ptr->ip) - || Tcl_GetCurrentNamespace(ptr->ip) != ptr->default_ns) { + if (Tcl_InterpDeleted(ptr->ip) || rbtk_invalid_namespace(ptr)) { DUMP1("ip is deleted"); Tcl_DecrRefCount(nameobj); Tcl_DecrRefCount(valobj); @@ -5682,8 +5680,7 @@ CONST char *ret; /* ip is deleted? */ - if (Tcl_InterpDeleted(ptr->ip) || ip_null_namespace(ptr->ip) - || Tcl_GetCurrentNamespace(ptr->ip) != ptr->default_ns) { + if (Tcl_InterpDeleted(ptr->ip) || rbtk_invalid_namespace(ptr)) { DUMP1("ip is deleted"); return rb_tainted_str_new2(""); } else { @@ -5780,8 +5777,7 @@ Tcl_IncrRefCount(valobj); /* ip is deleted? */ - if (Tcl_InterpDeleted(ptr->ip) || ip_null_namespace(ptr->ip) - || Tcl_GetCurrentNamespace(ptr->ip) != ptr->default_ns) { + if (Tcl_InterpDeleted(ptr->ip) || rbtk_invalid_namespace(ptr)) { DUMP1("ip is deleted"); Tcl_DecrRefCount(nameobj); Tcl_DecrRefCount(idxobj); @@ -5842,8 +5838,7 @@ CONST char *ret; /* ip is deleted? */ - if (Tcl_InterpDeleted(ptr->ip) || ip_null_namespace(ptr->ip) - || Tcl_GetCurrentNamespace(ptr->ip) != ptr->default_ns) { + if (Tcl_InterpDeleted(ptr->ip) || rbtk_invalid_namespace(ptr)) { DUMP1("ip is deleted"); return rb_tainted_str_new2(""); } else { @@ -5887,8 +5882,7 @@ StringValue(varname); /* ip is deleted? */ - if (Tcl_InterpDeleted(ptr->ip) || ip_null_namespace(ptr->ip) - || Tcl_GetCurrentNamespace(ptr->ip) != ptr->default_ns) { + if (Tcl_InterpDeleted(ptr->ip) || rbtk_invalid_namespace(ptr)) { DUMP1("ip is deleted"); return Qtrue; } @@ -5930,8 +5924,7 @@ StringValue(index); /* ip is deleted? */ - if (Tcl_InterpDeleted(ptr->ip) || ip_null_namespace(ptr->ip) - || Tcl_GetCurrentNamespace(ptr->ip) != ptr->default_ns) { + if (Tcl_InterpDeleted(ptr->ip) || rbtk_invalid_namespace(ptr)) { DUMP1("ip is deleted"); return Qtrue; } @@ -6524,7 +6517,7 @@ rb_define_method(ip, "allow_ruby_exit=", ip_allow_ruby_exit_set, 1); rb_define_method(ip, "delete", ip_delete, 0); rb_define_method(ip, "deleted?", ip_is_deleted_p, 0); - rb_define_method(ip, "null_namespace?", ip_has_null_namespace_p, 0); + rb_define_method(ip, "invalid_namespace?", ip_has_invalid_namespace_p, 0); rb_define_method(ip, "_eval", ip_eval, 1); rb_define_method(ip, "_toUTF8", ip_toUTF8, -1); rb_define_method(ip, "_fromUTF8", ip_fromUTF8, -1); -- 永井 秀利 (九工大 知能情報) nagai@ai.kyutech.ac.jp