Thread: [Fxruby-users] catching exceptions in event handlers
Status: Inactive
Brought to you by:
lyle
|
From: Emmanuel T. <emm...@wa...> - 2003-07-23 09:50:47
|
Hello,
I'm having the problem that my GUI app might have some bugs; in that
case, instead of seeing it exiting violently, dumping the stack on the
command line (which will never be seen by the user in most cases), i would
like to catch the exception and display a nice dialog box.
Wrapping the app.run call (i don't remember how it's called, but it's
something like that) in a begin/rescue block doesn't seem to catch this
exception.
So it would seem i need to wrap each event handler in a begin/rescue
block.
I thought about something like (didn't look at the code, untested
snippet, just to give the idea):
class FXWindow
def connect(event, &block)
begin
super
rescue
FXMessageBox("an error occured, here is the stacktrace, contact
the developer of the application"...)
exit
end
end
end
and the same for other ways to connect the events (ie event tables). i would
put that in a "exceptionfox.rb", and do a "require 'exceptionfox.rb'"
instead of "require 'fox'", so i wouldn't have to change my code. i could
also call a user-defined function when getting an exception.
i didn't try this approach yet (no time). but i'm wondering if it seems
possible, and if there is maybe a better solution?
i'm sure i'm not the first one facing this problem?
thank you,
emmanuel
|
|
From: Lyle J. <jl...@cf...> - 2003-07-23 13:03:30
|
Emmanuel Touzery wrote:
> I'm having the problem that my GUI app might have some bugs; in that
> case, instead of seeing it exiting violently, dumping the stack on the
> command line (which will never be seen by the user in most cases), i would
> like to catch the exception and display a nice dialog box.
> Wrapping the app.run call (i don't remember how it's called, but it's
> something like that) in a begin/rescue block doesn't seem to catch this
> exception.
Is it a standard Ruby exception, or is the Ruby interpreter (ruby)
seg-faulting? If it's the former (a regular exception), it /should/ be
raised all the way to the "top" and get caught in your begin-rescue
block around the call to FXApp#run.
> So it would seem i need to wrap each event handler in a begin/rescue
> block.
You might also see if the Fox.setIgnoreExceptions() method is a suitable
workaround; see the "Debugging Tricks" at the end of this page:
http://www.fxruby.org/doc/differences.html
> I thought about something like (didn't look at the code, untested
> snippet, just to give the idea):
>
> class FXWindow
> def connect(event, &block)
> begin
> super
> rescue
> FXMessageBox("an error occured, here is the stacktrace, contact
> the developer of the application"...)
> exit
> end
> end
> end
No, this wouldn't work. The connect() method just sets up the mapping
between a message type (e.g. SEL_COMMAND) and the block or method that
handles it. It doesn't actually execute the code.
> and the same for other ways to connect the events (ie event tables). i would
> put that in a "exceptionfox.rb", and do a "require 'exceptionfox.rb'"
> instead of "require 'fox'", so i wouldn't have to change my code. i could
> also call a user-defined function when getting an exception.
> i didn't try this approach yet (no time). but i'm wondering if it seems
> possible, and if there is maybe a better solution?
This sounds way too complicated, IMO. If wrapping the call to FXApp#run
with a "last-chance" begin-rescue block is failing to catch exceptions,
I would like to see that demonstrated and get it fixed. I think the best
solution is to get a good group of testers and get them to help you find
the bugs ;)
|
|
From: Emmanuel T. <emm...@wa...> - 2003-07-23 13:13:58
|
> Emmanuel Touzery wrote:
>
> > I'm having the problem that my GUI app might have some bugs; in that
> > case, instead of seeing it exiting violently, dumping the stack on the
> > command line (which will never be seen by the user in most cases), i
would
> > like to catch the exception and display a nice dialog box.
> > Wrapping the app.run call (i don't remember how it's called, but
it's
> > something like that) in a begin/rescue block doesn't seem to catch this
> > exception.
>
> Is it a standard Ruby exception, or is the Ruby interpreter (ruby)
> seg-faulting? If it's the former (a regular exception), it /should/ be
> raised all the way to the "top" and get caught in your begin-rescue
> block around the call to FXApp#run.
standard exception. for an interpreter crash there is not much to display
anyway ;O)
i want a backtrace so that i can debug.
i'm happy to read that FXApp#run is going to "forward me" the exception. but
it doesn't seem to work here (see code snippet at the end of the mail).
> This sounds way too complicated, IMO. If wrapping the call to FXApp#run
> with a "last-chance" begin-rescue block is failing to catch exceptions,
> I would like to see that demonstrated and get it fixed. I think the best
> solution is to get a good group of testers and get them to help you find
> the bugs ;)
maybe i'm doing something wrong, but how about this code:
click on file->open
#!/usr/bin/env ruby
require 'fox'
include Fox
class GlossaryMainWindow < FXMainWindow
include Responder
ID_OPEN,
ID_LAST = enum(FXMainWindow::ID_LAST, 2)
def initialize(app)
# Initialize base class first
super(app, "Glossary", nil, nil, DECOR_ALL, 0, 0, 400, 300)
FXMAPFUNC(SEL_COMMAND, ID_OPEN, :onCmdOpen)
# Make main window; set myself as the target
# setTarget(self)
# setSelector(ID_TITLE)
# Make menu bar
dragshell1 = FXToolbarShell.new(self, FRAME_RAISED|FRAME_THICK)
menubar = FXMenubar.new(self, dragshell1, LAYOUT_SIDE_TOP|LAYOUT_FILL_X)
FXToolbarGrip.new(menubar, menubar, FXMenubar::ID_TOOLBARGRIP,
TOOLBARGRIP_SINGLE)
# File menu
filemenu = FXMenuPane.new(self)
FXMenuTitle.new(menubar, "&File", nil, filemenu)
# File Menu entries
FXMenuCommand.new(filemenu,
"&Open... \tCtl-O\tOpen document file.",
@openicon, self, ID_OPEN)
end
def onCmdOpen(sender, sel, ptr)
pouf # <-- invalid code
end
# Create and show the main window
def create
super
show(PLACEMENT_SCREEN)
end
end
if $0 == __FILE__
# Construct an application
application = FXApp.new('Glossary', 'Emmanuel')
# Construct the main window
GlossaryMainWindow.new(application)
# Create and show the application windows
application.create
# Run the application
begin
application.run
rescue
FXMessageBox.error(self, MBOX_OK, "Error", "Boom!")
end
end
|
|
From: Lyle J. <jl...@cf...> - 2003-07-23 13:31:26
|
Emmanuel Touzery wrote: > i'm happy to read that FXApp#run is going to "forward me" the exception. but > it doesn't seem to work here (see code snippet at the end of the mail). Ahem. Emmanuel, when you run this program, you are correct that it raises an exception. Did you notice which line of code the backtrace was pointing to? ;) The exception that is raised in your onCmdOpen() method is being caught by the 'rescue' block at application.run. The code in that 'rescue' block raises yet another exception, though (hint: what does 'self' refer to in the call to FXMessageBox.error?). |
|
From: Emmanuel T. <emm...@wa...> - 2003-07-23 13:37:52
|
> Emmanuel Touzery wrote:
>
> > i'm happy to read that FXApp#run is going to "forward me" the exception.
but
> > it doesn't seem to work here (see code snippet at the end of the mail).
>
> Ahem.
>
> Emmanuel, when you run this program, you are correct that it raises an
> exception. Did you notice which line of code the backtrace was pointing
> to? ;)
>
> The exception that is raised in your onCmdOpen() method is being caught
> by the 'rescue' block at application.run. The code in that 'rescue'
> block raises yet another exception, though (hint: what does 'self' refer
> to in the call to FXMessageBox.error?).
not here..
i think we're not using the same version of fxruby:
C:\programs\glossary\test>ruby test.rb
test.rb:38:in `onCmdOpen': undefined local variable or method `pouf' for
#<Gloss
aryMainWindow:0x52d3c78> (NameError)
from test.rb:61:in `run'
from test.rb:61
i tried putting nothing in the rescue, or just a puts (before posting).
are you using some kind of development version of FXRuby? i'm testing under
windows2000 with the latest version on sourceforge. i tried yesterday under
linux as well and IIRC it didn't work either (but it was late, etc, i could
have did sth wrong).
emmanuel
|
|
From: Aaron S. <aa...@sc...> - 2003-07-23 13:58:48
|
At 15:40 +0100 23 Jul 2003, Emmanuel Touzery <emm...@wa...> wrote: > C:\programs\glossary\test>ruby test.rb > test.rb:38:in `onCmdOpen': undefined local variable or method `pouf' for > #<Gloss > aryMainWindow:0x52d3c78> (NameError) > from test.rb:61:in `run' > from test.rb:61 NameError exceptions don't get caught by a bare rescue since that's equivalent to "rescue StandardError". If you truly want to catch all exceptions you need to use "rescue Exception". -- Aaron Schrab aa...@sc... http://www.schrab.com/aaron/ [It is] best to confuse only one issue at a time. -- K&R |
|
From: Emmanuel T. <emm...@wa...> - 2003-07-23 14:06:39
|
Hello, > At 15:40 +0100 23 Jul 2003, Emmanuel Touzery <emm...@wa...> wrote: > > C:\programs\glossary\test>ruby test.rb > > test.rb:38:in `onCmdOpen': undefined local variable or method `pouf' for > > #<Gloss > > aryMainWindow:0x52d3c78> (NameError) > > from test.rb:61:in `run' > > from test.rb:61 > > NameError exceptions don't get caught by a bare rescue since that's > equivalent to "rescue StandardError". If you truly want to catch all > exceptions you need to use "rescue Exception". thank you! this was my problem! now how to display a dialog box at this stage, as Lyle remarked.. is there a nicer solution than to create a brand new FXApp object? sorry to ask so much, but i don't see examples to base myself from on this... emmanuel |
|
From: Lyle J. <jl...@cf...> - 2003-07-23 14:21:37
|
Emmanuel Touzery wrote:
> now how to display a dialog box at this stage, as Lyle remarked.. is there
> a nicer solution than to create a brand new FXApp object?
Use the main window as the owner for the dialog box. To do this you'll
need to save a reference to the main window in a local variable, e.g.
mainWin = GlossaryMainWindow.new(application)
and then pass that as the first argument to FXMessageBox.error:
FXMessageBox.error(mainWin, MBOX_OK, "Error", "Boom!")
Lyle
|
|
From: Lyle J. <jl...@cf...> - 2003-07-23 14:17:59
|
Aaron Schrab wrote: > At 15:40 +0100 23 Jul 2003, Emmanuel Touzery <emm...@wa...> wrote: >> C:\programs\glossary\test>ruby test.rb >> test.rb:38:in `onCmdOpen': undefined local variable or method `pouf' for >> #<Gloss >> aryMainWindow:0x52d3c78> (NameError) >> from test.rb:61:in `run' >> from test.rb:61 > > NameError exceptions don't get caught by a bare rescue since that's > equivalent to "rescue StandardError". If you truly want to catch all > exceptions you need to use "rescue Exception". Yep, Aaron beat me to it ;) When I went back and tried running Emmanuel's program I got different results under Ruby version 1.6.8 and 1.8.0. It turns out that for Ruby 1.6, the NameError exception is derived from ScriptError and not StandardError, so the plain 'rescue' won't catch it. In Ruby 1.8.0, which I originally used to run the program, NameError is now derived from StandardError, and so the plain 'rescue' /does/ catch it. So, in summary, FXRuby does appear to be doing the right thing as far as passing Ruby exceptions up the call chain. |