Closed pterjan closed 3 years ago
I can't reproduce the core dump with the current version of Ruby. Is this still a problem in your environment with the current version of Ruby?
I am still seing the problem:
[pterjan@mageia ~]$ DISPLAY= ruby -r tk -e ''
#<Thread:0x0000000001ddb5e8 /usr/share/gems/gems/tk-0.2.0/lib/tk.rb:1243 run> terminated with exception (report_on_exception is true):
Traceback (most recent call last):
3: from /usr/share/gems/gems/tk-0.2.0/lib/tk.rb:1246:in `block in <module:TkCore>'
2: from /usr/share/gems/gems/tk-0.2.0/lib/tk.rb:1246:in `new'
1: from /usr/share/gems/gems/tk-0.2.0/lib/tk.rb:32:in `initialize'
/usr/share/gems/gems/tk-0.2.0/lib/tk.rb:32:in `initialize': tcltklib: fail to Tk_Init(). couldn't connect to display "" (RuntimeError)
Traceback (most recent call last):
1: from /usr/share/rubygems/rubygems/core_ext/kernel_require.rb:92:in `require'
/usr/share/rubygems/rubygems/core_ext/kernel_require.rb:92:in `require': cannot load such file -- tk (LoadError)
3: from /usr/share/gems/gems/tk-0.2.0/lib/tk.rb:1246:in `block in <module:TkCore>'
2: from /usr/share/gems/gems/tk-0.2.0/lib/tk.rb:1246:in `new'
1: from /usr/share/gems/gems/tk-0.2.0/lib/tk.rb:32:in `initialize'
/usr/share/gems/gems/tk-0.2.0/lib/tk.rb:32:in `initialize': tcltklib: fail to Tk_Init(). couldn't connect to display "" (RuntimeError)
Tcl_AsyncDelete: async handler deleted by the wrong thread
Aborted (core dumped)
[pterjan@mageia ~]$ ruby -r tk -e ''
/usr/share/gems/gems/tk-0.2.0/lib/tk.rb:1495: warning: rb_safe_level will be removed in Ruby 3.0
/usr/share/gems/gems/tk-0.2.0/lib/tk.rb:1301: warning: rb_safe_level will be removed in Ruby 3.0
/usr/share/gems/gems/tk-0.2.0/lib/tk.rb:837: warning: rb_safe_level will be removed in Ruby 3.0
/usr/share/gems/gems/tk-0.2.0/lib/tk.rb:1301: warning: rb_safe_level will be removed in Ruby 3.0
/usr/share/gems/gems/tk-0.2.0/lib/tk.rb:1497: warning: rb_safe_level will be removed in Ruby 3.0
/usr/share/gems/gems/tk-0.2.0/lib/tk.rb:1301: warning: rb_safe_level will be removed in Ruby 3.0
/usr/share/gems/gems/tk-0.2.0/lib/tk.rb:1469: warning: rb_safe_level will be removed in Ruby 3.0
/usr/share/gems/gems/tk-0.2.0/lib/tk.rb:1301: warning: rb_safe_level will be removed in Ruby 3.0
/usr/share/gems/gems/tk-0.2.0/lib/tk.rb:1469: warning: rb_safe_level will be removed in Ruby 3.0
/usr/share/gems/gems/tk-0.2.0/lib/tk.rb:1301: warning: rb_safe_level will be removed in Ruby 3.0
/usr/share/gems/gems/tk-0.2.0/lib/tk.rb:2166: warning: rb_safe_level will be removed in Ruby 3.0
/usr/share/gems/gems/tk-0.2.0/lib/tk.rb:1301: warning: rb_safe_level will be removed in Ruby 3.0
/usr/share/gems/gems/tk-0.2.0/lib/tk.rb:2167: warning: rb_safe_level will be removed in Ruby 3.0
/usr/share/gems/gems/tk-0.2.0/lib/tk.rb:1301: warning: rb_safe_level will be removed in Ruby 3.0
/usr/share/gems/gems/tk-0.2.0/lib/tk.rb:2173: warning: rb_safe_level will be removed in Ruby 3.0
/usr/share/gems/gems/tk-0.2.0/lib/tk.rb:1301: warning: rb_safe_level will be removed in Ruby 3.0
/usr/share/gems/gems/tk-0.2.0/lib/tk.rb:2174: warning: rb_safe_level will be removed in Ruby 3.0
/usr/share/gems/gems/tk-0.2.0/lib/tk.rb:1301: warning: rb_safe_level will be removed in Ruby 3.0
/usr/share/gems/gems/tk-0.2.0/lib/tk.rb:2180: warning: rb_safe_level will be removed in Ruby 3.0
/usr/share/gems/gems/tk-0.2.0/lib/tk.rb:1301: warning: rb_safe_level will be removed in Ruby 3.0
/usr/share/gems/gems/tk-0.2.0/lib/tk.rb:2608: warning: rb_set_safe_level_force will be removed in Ruby 3.0
/usr/share/gems/gems/tk-0.2.0/lib/tk.rb:2054: warning: rb_safe_level will be removed in Ruby 3.0
/usr/share/gems/gems/tk-0.2.0/lib/tk.rb:1301: warning: rb_safe_level will be removed in Ruby 3.0
/usr/share/gems/gems/tk-0.2.0/lib/tk.rb:1456: warning: rb_eval_cmd will be removed in Ruby 3.0
/usr/share/gems/gems/tk-0.2.0/lib/tk.rb:1479: warning: rb_safe_level will be removed in Ruby 3.0
/usr/share/gems/gems/tk-0.2.0/lib/tk.rb:1315: warning: rb_safe_level will be removed in Ruby 3.0
[pterjan@mageia ~]$ ruby --version
ruby 2.7.1p83 (2020-03-31 revision a0c7c23c9c) [x86_64-linux]
OK. Can you provide more details about your environment, such as operating system, and versions of tcl/tk in use?
Can you also try this and see if you get the same error: DISPLAY= ruby -r tk -e 'at_exit{exit!}'
Same problem with the at_exit
This is on Mageia Linux x86_64, using tcl/tk 8.6.10
Can you try with tcl/tk 8.5? I'm not sure how well ruby-tk supports tcl/tk 8.6. Support was added for tcl/tk 8.6 in 2014, but I'm guessing tcl/tk 8.5 is better supported.
I looked more into it last night and this is what I found.
It seems RUN_EVENTLOOP_ON_MAIN_THREAD
is true on cygwin and MacOS X which means the problem can not occur there. I confirmed that setting it to true fixes the problem as there is no thread to mismatch.
Here the interpreter gets created in a thread, and TclTkIp.new
throws an exception and I guess the thread ends so cleanup ends up happening outside of it:
INTERP_THREAD = Thread.new{
begin
#Thread.current[:interp] = interp = TclTkIp.new(name, opts)
interp = TclTkIp.new(name, opts)
rescue => e
Thread.current[:interp] = e
raise e
end
Further down there is a block to run the main loop and that one specifically handles the same problem by deleting the interpreter before the thread exists:
ensure
# interp must be deleted before the thread for interp is dead.
# If not, raise Tcl_Panic on Tcl_AsyncDelete because async handler
# deleted by the wrong thread.
interp.delete
end
So my understanding is that the problem occurs on platforms where RUN_EVENTLOOP_ON_MAIN_THREAD
is true, when Tk_Init fails.
I tried this which seems to work:
--- /tmp/tcltklib.c 2020-10-06 12:19:28.491065555 +0000
+++ tcltklib.c 2020-10-06 13:20:46.869578812 +0000
@@ -6256,19 +6256,26 @@
st = ruby_tcl_stubs_init();
/* from Tcl_AppInit() */
if (with_tk) {
+ char *error;
DUMP1("Tk_Init");
st = ruby_tk_stubs_init(ptr->ip);
+ if (st != TCLTK_STUBS_OK) {
+ error = Tcl_GetStringResult(ptr->ip);
+ ip_finalize(ptr->ip);
+ Tcl_DeleteInterp(ptr->ip);
+ Tcl_Release(ptr->ip);
+ ptr->ip = (Tcl_Interp*)NULL;
+ }
switch(st) {
+
case TCLTK_STUBS_OK:
break;
case NO_Tk_Init:
rb_raise(rb_eLoadError, "tcltklib: can't find Tk_Init()");
case FAIL_Tk_Init:
- rb_raise(rb_eRuntimeError, "tcltklib: fail to Tk_Init(). %s",
- Tcl_GetStringResult(ptr->ip));
+ rb_raise(rb_eRuntimeError, "tcltklib: fail to Tk_Init(). %s", error);
case FAIL_Tk_InitStubs:
- rb_raise(rb_eRuntimeError, "tcltklib: fail to Tk_InitStubs(). %s",
- Tcl_GetStringResult(ptr->ip));
+ rb_raise(rb_eRuntimeError, "tcltklib: fail to Tk_InitStubs(). %s", error);
default:
rb_raise(rb_eRuntimeError, "tcltklib: unknown error(%d) on ruby_tk_stubs_init", st);
}
@pterjan Thank you very much for debugging this issue. I'll try your patch later today.
@pterjan I slightly modified your patch and incorporated it into #20. Can you test pull request #20 and see if it works for you. If so, I'll probably be releasing that branch as 0.3.0.
Thank you, I can confirm this is fixed with pull request #20