[BUG] ruby/tcltk reentrancy bug

Hello,

I have found a bug in ruby’s tcltk interface.
Following code demonstrates problem:

···

require ‘tk’

@proc3=proc{ puts ‘proc3, the old one’}

proc2a=proc{
puts ‘proc2 start’

IF EXCEPTION IS UNHANDLED, THIS WILL CRASH

something_not_defined
puts ‘proc2 end’
}

proc2b=proc{
puts ‘proc2 start’
@proc3=proc{
puts ‘proc3 start’
# IF EXCEPTION IS UNHANDLED, THIS WILL CRASH
# WHEN CALLED FROM ANYWHERE
something_not_defined
puts ‘proc3 end’
}
puts ‘proc2 end’
}

proc1=proc{
puts ‘proc1 start’
@dialog1=TkToplevel.new(@root)
TkButton.new(@dialog1, ‘text’=>‘proc2a’, ‘command’=>proc2a).pack
TkButton.new(@dialog1, ‘text’=>‘proc2b’, ‘command’=>proc2b).pack
@dialog1.title ‘dialog 1’
@dialog1.transient(@parent)
@dialog1.withdraw
@dialog1.update
@dialog1.deiconify
@dialog1.grab
@dialog1.wait_destroy
puts ‘proc1 end’
}

def runproc3
@proc3.call
end

@root=TkRoot.new
TkButton.new(@root, ‘text’=>‘proc1’, ‘command’=>proc1).pack
TkButton.new(@root, ‘text’=>‘runproc3’, ‘command’=>proc{runproc3}).pack
Tk.mainloop

To crash follow these steps:
Variant A:
press button ‘proc1’ then ‘proc2a’.
Variant B:
press button ‘proc1’, ‘proc2b’, close dialog, then press ‘runproc3’.

Problem depends on wait_destroy call reentrancy.
Bug happen when exception is raised, but not handled inside
reentrant part.

Problem appears also when Proc object is defined in lexical
environment of part called in reentrant way. (Variant B)

Affected ruby versions:
ruby 1.6.7 (2002-03-19) [i386-linux]

This Windows version seems to survive above example:
ruby 1.6.7 (2002-03-01) [i586-mswin32]

But following code with more deep reentrancy will kill both
windows and linux versions of ruby:

require ‘tk’

class Dialog
def initialize(parent, &block)
@parent=parent
@block=block
end
def run
@dialog=TkToplevel.new(@parent)
@block.call @dialog
@dialog.title ‘dialog’
@dialog.transient(@parent)
@dialog.withdraw
@dialog.update
@dialog.deiconify
@dialog.grab
@dialog.wait_destroy
end
def exit
@dialog.destroy
end
end

w1=TkRoot.new
TkButton.new(w1, ‘text’=>‘button 1’,
‘command’=>proc{
puts 'button1 start’
d1=Dialog.new(w1){|w2|
TkButton.new(w2, ‘text’=>‘button 2’,
‘command’=>proc{
d2=Dialog.new(w2){|w3|
puts 'button2 start’
TkButton.new(w3, ‘text’=>‘button 3’,
‘command’=>proc{
d3=Dialog.new(w3){|w4|
puts 'button3 start’
TkLabel.new(w4, ‘text’=>‘label’).pack
something_not_defined # <-- unhandled exception
puts ‘button3 end’
}
d3.run
}).pack
puts ‘button2 end’
}
d2.run
}).pack
}
d1.run
puts ‘button1 end’
}).pack
Tk.mainloop

To crash: press buttons as they appear.

I think that this is bug in ruby since, when no exception
occurs or it is handled before return from reentrancy, no crash
will happen.

Best regards,

Jakub Travnik,
jabber://jtra@jabber.com

   def run

[...]

     @dialog.wait_destroy

Well, it crash with 1.6.7

Can you try with 1.7.3 : it seems to work and give the error message

undefined local variable or method `something_not_defined' for
#<Object:0x401bda74>

Guy Decoux

Hi,

···

In message “Re: [BUG] ruby/tcltk reentrancy bug” on 02/09/20, ts decoux@moulon.inra.fr writes:

Well, it crash with 1.6.7

Can you try with 1.7.3 : it seems to work and give the error message

I will backport 1.7 tcltklib.c to 1.6.

						matz.

I will backport 1.7 tcltklib.c to 1.6.

Should we be looking out for 1.6.8 shortly, then? A search for
“backport” turns up quite a few refs on Ruby-Talk since March…

  					matz.
    Thank you,
    Hugh
···

On Fri, 20 Sep 2002, Yukihiro Matsumoto wrote:

Hi,

···

In message “Re: [BUG] ruby/tcltk reentrancy bug” on 02/09/20, Hugh Sasse Staff Elec Eng hgs@dmu.ac.uk writes:

Should we be looking out for 1.6.8 shortly, then? A search for
“backport” turns up quite a few refs on Ruby-Talk since March…

Hopefully. I have a few leftovers to fix. I encourage people to try
the stable snapshot, and report me if you find anything to fix.

						matz.