diff options
Diffstat (limited to 'ext/tk')
-rw-r--r-- | ext/tk/lib/multi-tk.rb | 182 | ||||
-rw-r--r-- | ext/tk/lib/tk/optiondb.rb | 12 | ||||
-rw-r--r-- | ext/tk/lib/tk/text.rb | 2 | ||||
-rw-r--r-- | ext/tk/sample/tkoptdb-safeTk.rb | 23 |
4 files changed, 186 insertions, 33 deletions
diff --git a/ext/tk/lib/multi-tk.rb b/ext/tk/lib/multi-tk.rb index 7de36e1fb5..2536b382fd 100644 --- a/ext/tk/lib/multi-tk.rb +++ b/ext/tk/lib/multi-tk.rb @@ -112,18 +112,32 @@ class MultiTkIp ###################################### def set_safe_level(safe) + @safe_level[0] = safe @cmd_queue.enq([@system, 'set_safe_level', safe]) self end + def safe_level=(safe) + set_safe_level(safe) + end def self.set_safe_level(safe) __getip.set_safe_level(safe) self end + def self.safe_level=(safe) + self.set_safe_level(safe) + end + def safe_level + @safe_level[0] + end + def self.safe_level + __getip.safe_level + end + + def _create_receiver_and_watchdog(lvl = $SAFE) + lvl = $SAFE if lvl < $SAFE - def _create_receiver_and_watchdog() # command-procedures receiver - receiver = Thread.new{ - safe_level = $SAFE + receiver = Thread.new(lvl){|safe_level| loop do thread, cmd, *args = @cmd_queue.deq if thread == @system @@ -143,17 +157,88 @@ class MultiTkIp # procedure begin ret = proc{$SAFE = safe_level; cmd.call(*args)}.call - rescue SystemExit + rescue SystemExit => e # delete IP unless @interp.deleted? - # if @interp._invoke('info', 'command', '.') != "" - # @interp._invoke('destroy', '.') - # end - # @interp.delete - @interp._eval_without_enc('exit') + @slave_ip_tbl.each_value{|subip| + unless subip.deleted? + begin + subip._invoke('destroy', '.') + rescue Exception + end + subip.delete + # subip._invoke('exit') + # subip._eval_without_enc('exit') + end + } + begin + @interp._invoke('destroy', '.') + rescue Exception + end + if safe? + # do 'exit' to call the delete_hook procedure + @interp._eval_without_enc('exit') + else + @interp.delete + end + end + if e.backtrace[0] =~ /\`exit'/ + _check_and_return(thread, MultiTkIp_OK.new(true)) + elsif e.backtrace[0] =~ /\`(exit!|abort)'/ + _check_and_return(thread, MultiTkIp_OK.new(false)) + else + _check_and_return(thread, MultiTkIp_OK.new(nil)) end - _check_and_return(thread, MultiTkIp_OK.new(nil)) break + rescue SecurityError => e + # ignore security error in 'exit', 'exit!', and 'abort' + if e.backtrace[0] =~ /\`exit'/ + unless @interp.deleted? + @slave_ip_tbl.each_value{|subip| + unless subip.deleted? + begin + subip._invoke('destroy', '.') + rescue Exception + end + subip.delete + # subip._invoke('exit') + # subip._eval_without_enc('exit') + end + } + begin + @interp._invoke('destroy', '.') + rescue Exception + end + # @interp.delete + @interp._eval_without_enc('exit') + end + _check_and_return(thread, MultiTkIp_OK.new(true)) + break + elsif e.backtrace[0] =~ /\`(exit!|abort)'/ + unless @interp.deleted? + @slave_ip_tbl.each_value{|subip| + unless subip.deleted? + begin + subip._invoke('destroy', '.') + rescue Exception + end + subip.delete + # subip._invoke('exit') + # subip._eval_without_enc('exit') + end + } + begin + @interp._invoke('destroy', '.') + rescue Exception + end + # @interp.delete + @interp._eval_without_enc('exit') + end + _check_and_return(thread, MultiTkIp_OK.new(false)) + break + else + _check_and_return(thread, e) + end rescue Exception => e # raise exception _check_and_return(thread, e) @@ -230,9 +315,11 @@ class MultiTkIp @threadgroup = Thread.current.group + @safe_level = [$SAFE] + @cmd_queue = Queue.new - @cmd_receiver, @receiver_watchdog = _create_receiver_and_watchdog() + @cmd_receiver, @receiver_watchdog = _create_receiver_and_watchdog(@safe_level[0]) @threadgroup.add @cmd_receiver @threadgroup.add @receiver_watchdog @@ -535,17 +622,37 @@ class MultiTkIp name, safe, safe_opts, tk_opts = _parse_slaveopts(keys) + safe = 4 if safe && !safe.kind_of?(Fixnum) + if safeip == nil # create master-ip @interp = TclTkIp.new(name, _keys2opts(tk_opts)) @ip_name = nil + if safe + safe = $SAFE if safe < $SAFE + @safe_level = [safe] + else + @safe_level = [$SAFE] + end else # create slave-ip if safeip || master.safe? @interp, @ip_name = master.__create_safe_slave_obj(safe_opts, name, tk_opts) + if safe + safe = master.safe_level if safe < master.safe_level + @safe_level = [safe] + else + @safe_level = [4] + end else @interp, @ip_name = master.__create_trusted_slave_obj(name, tk_opts) + if safe + safe = master.safe_level if safe < master.safe_level + @safe_level = [safe] + else + @safe_level = [master.safe_level] + end end @set_alias_proc = proc{|name| master._invoke('interp', 'alias', @ip_name, name, '', name) @@ -558,7 +665,7 @@ class MultiTkIp @cmd_queue = Queue.new - @cmd_receiver, @receiver_watchdog = _create_receiver_and_watchdog() + @cmd_receiver, @receiver_watchdog = _create_receiver_and_watchdog(@safe_level[0]) @threadgroup.add @cmd_receiver @threadgroup.add @receiver_watchdog @@ -634,24 +741,25 @@ class << MultiTkIp alias __new new private :__new - def new_master(keys={}, &b) + + def new_master(keys={}) ip = __new(__getip, nil, keys) - ip.eval_proc(&b) if b + ip.eval_proc(proc{$SAFE=ip.safe_level; Proc.new}.call) if block_given? ip end alias new new_master - def new_slave(keys={}, &b) + def new_slave(keys={}) ip = __new(__getip, false, keys) - ip.eval_proc(&b) if b + ip.eval_proc(proc{$SAFE=ip.safe_level; Proc.new}.call) if block_given? ip end alias new_trusted_slave new_slave - def new_safe_slave(keys={},&b) + def new_safe_slave(keys={}) ip = __new(__getip, true, keys) - ip.eval_proc(&b) if b + ip.eval_proc(proc{$SAFE=ip.safe_level; Proc.new}.call) if block_given? ip end alias new_safeTk new_safe_slave @@ -857,12 +965,15 @@ class MultiTkIp if cmd.kind_of?(String) xcmd = cmd xargs = args - cmd = proc{ TkComm._get_eval_string(eval(xcmd, *xargs)) } + cmd = proc{ + $SAFE=@safe_level[0] + TkComm._get_eval_string(eval(xcmd, *xargs)) + } args = [] end # check - unless cmd.kind_of?(Proc) + unless cmd.kind_of?(Proc) || cmd.kind_of?(Method) raise RuntimeError, "A Proc object is expected for the 'cmd' argument" end @@ -919,11 +1030,11 @@ class MultiTkIp end private :eval_proc_core - def eval_callback(cmd = Proc.new, *args) + def eval_callback(cmd = proc{$SAFE=@safe_level[0]; Proc.new}.call, *args) eval_proc_core(false, cmd, *args) end - def eval_proc(cmd = Proc.new, *args) + def eval_proc(cmd = proc{$SAFE=@safe_level[0]; Proc.new}.call, *args) eval_proc_core(true, cmd, *args) end alias call eval_proc @@ -931,7 +1042,7 @@ class MultiTkIp end class << MultiTkIp # class method - def eval_proc(cmd = Proc.new, *args) + def eval_proc(cmd = proc{$SAFE=__getip.safe_level; Proc.new}.call, *args) # class ==> interp object __getip.eval_proc(cmd, *args) end @@ -994,6 +1105,10 @@ class << MultiTkIp __getip.safe? end + def exit(st = 0) + __getip.exit(st) + end + def restart(app_name = nil, keys = {}) init_ip_internal @@ -1187,17 +1302,36 @@ class MultiTkIp end def delete + @slave_ip_tbl.each_value{|subip| + unless subip.deleted? + begin + subip._invoke('destroy', '.') + rescue Exception + end + subip.delete + #subip._invoke('exit') + end + } if safe? # do 'exit' to call the delete_hook procedure @interp._eval_without_enc('exit') end - @interp.delete + @interp.delete unless @interp.deleted? end def deleted? @interp.deleted? end + def exit(st = 0) + if master? + Kernel.exit(st) + else + delete + st + end + end + def restart(app_name = nil, keys = {}) _init_ip_internal(@@INIT_IP_ENV, @@ADD_TK_PROCS) diff --git a/ext/tk/lib/tk/optiondb.rb b/ext/tk/lib/tk/optiondb.rb index db735d929a..1211dda4a8 100644 --- a/ext/tk/lib/tk/optiondb.rb +++ b/ext/tk/lib/tk/optiondb.rb @@ -17,15 +17,15 @@ module TkOptionDB end def add(pat, value, pri=None) - if $SAFE >= 4 - fail SecurityError, "can't call 'TkOptionDB.add' at $SAFE >= 4" - end + # if $SAFE >= 4 + # fail SecurityError, "can't call 'TkOptionDB.add' at $SAFE >= 4" + # end tk_call('option', 'add', pat, value, pri) end def clear - if $SAFE >= 4 - fail SecurityError, "can't call 'TkOptionDB.crear' at $SAFE >= 4" - end + # if $SAFE >= 4 + # fail SecurityError, "can't call 'TkOptionDB.crear' at $SAFE >= 4" + # end tk_call_without_enc('option', 'clear') end def get(win, name, klass) diff --git a/ext/tk/lib/tk/text.rb b/ext/tk/lib/tk/text.rb index bd4586e4e2..acdc905fe0 100644 --- a/ext/tk/lib/tk/text.rb +++ b/ext/tk/lib/tk/text.rb @@ -722,7 +722,7 @@ class TkText<TkTextWin def tag_remove(tag, *indices) tk_send_without_enc('tag', 'remove', _get_eval_enc_str(tag), - *(indces.collect{|idx| _get_eval_enc_str(idx)})) + *(indices.collect{|idx| _get_eval_enc_str(idx)})) self end diff --git a/ext/tk/sample/tkoptdb-safeTk.rb b/ext/tk/sample/tkoptdb-safeTk.rb index a5e394b230..ebbc7b486f 100644 --- a/ext/tk/sample/tkoptdb-safeTk.rb +++ b/ext/tk/sample/tkoptdb-safeTk.rb @@ -26,10 +26,29 @@ else File.dirname(__FILE__))) end file = File.expand_path('tkoptdb.rb', File.dirname(__FILE__)) -MultiTkIp.new_safeTk{ - ent.each{|pat, val| TkOptionDB.add(pat, val)} + +ip = MultiTkIp.new_safeTk{ + # When a block is given to 'new_safeTk' method, + # the block is evaluated on $SAFE==4. + ent.each{|pat, val| Tk.tk_call('option', 'add', pat, val)} +} + +=begin +ip.eval_proc{ + # When a block is given to 'eval_proc' method, + # the block is evaluated on the IP's current safe level. + # So, the followings raises exceptions. load file } +=end + +ip.eval_proc(proc{ + # When a Procedure object is given to 'eval_proc' method as an argument, + # the proc is evaluated on the proc's binding. + # So, the followings are evaluated on $SAFE==0 + load file +}) + # Tk.mainloop is ignored on the slave-IP Tk.mainloop |