summaryrefslogtreecommitdiff
path: root/ext/tk
diff options
context:
space:
mode:
Diffstat (limited to 'ext/tk')
-rw-r--r--ext/tk/lib/multi-tk.rb184
-rw-r--r--ext/tk/lib/remote-tk.rb13
-rw-r--r--ext/tk/lib/tk/timer.rb7
-rw-r--r--ext/tk/tkutil.c11
4 files changed, 180 insertions, 35 deletions
diff --git a/ext/tk/lib/multi-tk.rb b/ext/tk/lib/multi-tk.rb
index ee6b76ec6c..dea1661c65 100644
--- a/ext/tk/lib/multi-tk.rb
+++ b/ext/tk/lib/multi-tk.rb
@@ -165,6 +165,10 @@ class MultiTkIp
unless ip.deleted?
ip._split_tklist(ip._invoke('interp', 'slaves')).each{|name|
begin
+ ip._eval_without_enc("#{name} eval {foreach i [after info] {after cancel $i}}")
+ rescue Exception
+ end
+ begin
# ip._invoke('interp', 'eval', name, 'destroy', '.')
ip._invoke(name, 'eval', 'destroy', '.')
rescue Exception
@@ -183,10 +187,12 @@ class MultiTkIp
end
end
=end
- if ip._invoke('interp', 'exists', name) == '1'
- begin
- ip._invoke('interp', 'delete', name)
- rescue Exception
+ unless ip.deleted?
+ if ip._invoke('interp', 'exists', name) == '1'
+ begin
+ ip._invoke('interp', 'delete', name)
+ rescue Exception
+ end
end
end
}
@@ -199,6 +205,7 @@ class MultiTkIp
# command-procedures receiver
receiver = Thread.new(lvl){|safe_level|
loop do
+ break if @interp.deleted?
thread, cmd, *args = @cmd_queue.deq
if thread == @system
# control command
@@ -222,39 +229,66 @@ class MultiTkIp
@slave_ip_tbl.each{|name, subip|
_destroy_slaves_of_slaveIP(subip)
begin
- subip._invoke('destroy', '.')
+ subip._eval_without_enc("foreach i [after info] {after cancel $i}")
rescue Exception
end
+=begin
+ begin
+ subip._invoke('destroy', '.') unless subip.deleted?
+ rescue Exception
+ end
+=end
begin
# safe_base?
@interp._eval_without_enc("::safe::interpConfigure #{name}")
@interp._eval_without_enc("::safe::interpDelete #{name}")
rescue Exception
+ if subip.respond_to?(:safe_base?) && subip.safe_base? &&
+ !subip.deleted?
+ # do 'exit' to call the delete_hook procedure
+ begin
+ subip._eval_without_enc('exit')
+ rescue Exception
+ end
+ else
+ begin
+ subip.delete unless subip.deleted?
+ rescue Exception
+ end
+ end
end
- if subip.respond_to?(:safe_base?) && subip.safe_base? && !subip.deleted?
- # do 'exit' to call the delete_hook procedure
- subip._eval_without_enc('exit')
- end
- subip.delete unless subip.deleted?
}
begin
- @interp._invoke('destroy', '.')
+ @interp._eval_without_enc("foreach i [after info] {after cancel $i}")
+ rescue Exception
+ end
+ begin
+ @interp._invoke('destroy', '.') unless @interp.deleted?
rescue Exception
end
-
if @safe_base && !@interp.deleted?
# do 'exit' to call the delete_hook procedure
@interp._eval_without_enc('exit')
+ else
+ @interp.delete unless @interp.deleted?
end
-
- @interp.delete unless @interp.deleted?
end
+
if e.backtrace[0] =~ /^(.+?):(\d+):in `(exit|exit!|abort)'/
_check_and_return(thread, MultiTkIp_OK.new($3 == 'exit'))
else
_check_and_return(thread, MultiTkIp_OK.new(nil))
end
+
+ if master? && !safe? && allow_ruby_exit?
+=begin
+ ObjectSpace.each_object(TclTkIp){|obj|
+ obj.delete unless obj.deleted?
+ }
+=end
+ exit
+ end
break
rescue SecurityError => e
@@ -265,32 +299,52 @@ class MultiTkIp
@slave_ip_tbl.each_value{|subip|
_destroy_slaves_of_slaveIP(subip)
begin
- subip._invoke('destroy', '.')
+ subip._eval_without_enc("foreach i [after info] {after cancel $i}")
rescue Exception
end
+=begin
+ begin
+ subip._invoke('destroy', '.') unless subip.deleted?
+ rescue Exception
+ end
+=end
begin
# safe_base?
@interp._eval_without_enc("::safe::interpConfigure #{name}")
@interp._eval_without_enc("::safe::interpDelete #{name}")
rescue Exception
+ if subip.respond_to?(:safe_base?) && subip.safe_base? &&
+ !subip.deleted?
+ # do 'exit' to call the delete_hook procedure
+ begin
+ subip._eval_without_enc('exit')
+ rescue Exception
+ end
+ else
+ begin
+ subip.delete unless subip.deleted?
+ rescue Exception
+ end
+ end
end
- if subip.respond_to?(:safe_base?) && subip.safe_base? && !subip.deleted?
- subip._eval_without_enc('exit')
- end
- subip.delete unless subip.deleted?
}
begin
- @interp._invoke('destroy', '.')
+ @interp._eval_without_enc("foreach i [after info] {after cancel $i}")
rescue Exception
end
-
+=begin
+ begin
+ @interp._invoke('destroy', '.') unless @interp.deleted?
+ rescue Exception
+ end
+=end
if @safe_base && !@interp.deleted?
# do 'exit' to call the delete_hook procedure
@interp._eval_without_enc('exit')
+ else
+ @interp.delete unless @interp.deleted?
end
-
- @interp.delete unless @interp.deleted?
end
_check_and_return(thread, MultiTkIp_OK.new(ret))
break
@@ -377,6 +431,8 @@ class MultiTkIp
@threadgroup = Thread.current.group
+ @safe_base = false
+
@safe_level = [$SAFE]
@cmd_queue = Queue.new
@@ -754,6 +810,7 @@ class MultiTkIp
if safeip == nil
# create master-ip
@interp = TclTkIp.new(name, _keys2opts(tk_opts))
+
@ip_name = nil
if safe
safe = $SAFE if safe < $SAFE
@@ -1268,6 +1325,22 @@ class << MultiTkIp
end
end
+ def allow_ruby_exit?
+ __getip.allow_ruby_exit?
+ end
+
+ def allow_ruby_exit= (mode)
+ __getip.allow_ruby_exit = mode
+ end
+
+ def delete
+ __getip.delete
+ end
+
+ def deleteed?
+ __getip.deleted?
+ end
+
def exit(st = 0)
__getip.exit(st)
end
@@ -1444,10 +1517,10 @@ class MultiTkIp
end
@interp.mainloop(check_root)
end
- rescue StandardError
+ #rescue StandardError
+ rescue Exception
if TclTkLib.mainloop_abort_on_exception != nil
- STDERR.print("Warning: Tk mainloop on ", @interp.inspect,
- " receives ", $!.class.inspect,
+ STDERR.print("Warning: Tk mainloop receives ", $!.class.inspect,
" exception (ignore) : ", $!.message, "\n");
end
retry
@@ -1468,22 +1541,65 @@ class MultiTkIp
@safe_base
end
+ def allow_ruby_exit?
+ @interp.allow_ruby_exit?
+ end
+
+ def allow_ruby_exit= (mode)
+ @interp.allow_ruby_exit = mode
+ end
+
def delete
@slave_ip_tbl.each_value{|subip|
- unless subip.deleted?
- begin
- subip._invoke('destroy', '.')
- rescue Exception
+ _destroy_slaves_of_slaveIP(subip)
+=begin
+ begin
+ subip._invoke('destroy', '.') unless subip.deleted?
+ rescue Exception
+ end
+=end
+ begin
+ subip._eval_without_enc("foreach i [after info] {after cancel $i}")
+ rescue Exception
+ end
+ begin
+ # safe_base?
+ @interp._eval_without_enc("::safe::interpConfigure #{name}")
+ @interp._eval_without_enc("::safe::interpDelete #{name}")
+ rescue Exception
+ if subip.respond_to?(:safe_base?) && subip.safe_base? &&
+ !subip.deleted?
+ # do 'exit' to call the delete_hook procedure
+ begin
+ subip._eval_without_enc('exit')
+ rescue Exception
+ end
+ else
+ begin
+ subip.delete unless subip.deleted?
+ rescue Exception
+ end
end
- subip.delete
- #subip._invoke('exit')
end
}
- if safe?
+
+ begin
+ @interp._eval_without_enc("foreach i [after info] {after cancel $i}")
+ rescue Exception
+ end
+=begin
+ begin
+ @interp._invoke('destroy', '.') unless @interp.deleted?
+ rescue Exception
+ end
+=end
+ if @safe_base && !@interp.deleted?
# do 'exit' to call the delete_hook procedure
@interp._eval_without_enc('exit')
+ else
+ @interp.delete unless @interp.deleted?
end
- @interp.delete unless @interp.deleted?
+ self
end
def deleted?
diff --git a/ext/tk/lib/remote-tk.rb b/ext/tk/lib/remote-tk.rb
index 85888b158a..d09b2289e6 100644
--- a/ext/tk/lib/remote-tk.rb
+++ b/ext/tk/lib/remote-tk.rb
@@ -68,6 +68,7 @@ class RemoteTkIp
end
@interp = MultiTkIp.__getip
+ @interp.allow_ruby_exit = false
@appname = @interp._invoke('tk', 'appname')
@remote = remote_ip.dup.freeze
if displayof.kind_of?(TkWindow)
@@ -249,6 +250,18 @@ class RemoteTkIp
_appsend(false, false, 'interp issafe')
end
+ def safe_base?
+ false
+ end
+
+ def allow_ruby_exit?
+ false
+ end
+
+ def allow_ruby_exit= (mode)
+ fail RuntimeError, 'cannot change mode of the remote interpreter'
+ end
+
def delete
_appsend(false, true, 'exit')
end
diff --git a/ext/tk/lib/tk/timer.rb b/ext/tk/lib/tk/timer.rb
index fa0a582205..79d7ef55fa 100644
--- a/ext/tk/lib/tk/timer.rb
+++ b/ext/tk/lib/tk/timer.rb
@@ -28,7 +28,6 @@ class TkTimer
# class methods
###############################
def self.callback(obj_id)
- @after_id = nil
ex_obj = Tk_CBTBL[obj_id]
return "" if ex_obj == nil; # canceled
ex_obj.cb_call
@@ -59,6 +58,7 @@ class TkTimer
###############################
def do_callback
@in_callback = true
+ @after_id = nil
begin
@return_value = @current_proc.call(self)
rescue SystemExit
@@ -86,6 +86,10 @@ class TkTimer
end
def set_callback(sleep, args=nil)
+ if TkCore::INTERP.deleted?
+ self.cancel
+ return self
+ end
@after_script = "rb_after #{@id}"
@after_id = tk_call_without_enc('after', sleep, @after_script)
@current_args = args
@@ -313,6 +317,7 @@ class TkTimer
Tk_CBTBL[@id] = self
@do_loop = @loop_exec
@current_pos = 0
+ @after_id = nil
@init_sleep = 0
@init_proc = nil
diff --git a/ext/tk/tkutil.c b/ext/tk/tkutil.c
index b3e79430dd..aaa77b1aa8 100644
--- a/ext/tk/tkutil.c
+++ b/ext/tk/tkutil.c
@@ -9,6 +9,7 @@
************************************************/
#include "ruby.h"
+#include "rubysig.h"
#include "st.h"
static VALUE cMethod;
@@ -1133,6 +1134,13 @@ cbsubst_scan_args(self, arg_key, val_ary)
char *ptr;
volatile VALUE dst = rb_ary_new2(len);
volatile VALUE proc;
+ int thr_crit_bup;
+ VALUE old_gc;
+
+ thr_crit_bup = rb_thread_critical;
+ rb_thread_critical = Qtrue;
+
+ old_gc = rb_gc_disable();
Data_Get_Struct(rb_const_get(self, ID_SUBST_INFO),
struct cbsubst_info, inf);
@@ -1161,6 +1169,9 @@ cbsubst_scan_args(self, arg_key, val_ary)
}
}
+ if (old_gc == Qfalse) rb_gc_enable();
+ rb_thread_critical = thr_crit_bup;
+
return dst;
}