FXRuby default error handler

Hi,

I’m using FXRuby for building a database front-end. I have quite a lot
of classes now, made up of multiple methods each. Most of the time I use
rescue blocks in case an exception is raised by the framemork. But doing
that in every method of every class is really tedious.

If an exception is raised from a method without a rescue block, the
problem is that my application quits, since the application “run” method
stops.

begin

$app = MyApp.new
$app.create
$app.run

rescue Exception => e

DbError.show("", e)

end

I was wondering if we could define some sort of “default error handler”
for errors raised from the framework, in order to avoid both the
application crash, and the “one rescue per method” solution…

Thanks!

Philippe L.

Philippe L. wrote:

end

I was wondering if we could define some sort of “default error handler”
for errors raised from the framework, in order to avoid both the
application crash, and the “one rescue per method” solution…

That’s a good question.

I usually just try to make “one rescue per method” as painless as
possible, by writing wrapper methods. Still, that’s “one wrapper per
method”, which is only a slight improvement.

On 10/8/07, Joel VanderWerf [email protected] wrote:

stops.
DbError.show(“”, e)
I usually just try to make “one rescue per method” as painless as
possible, by writing wrapper methods. Still, that’s “one wrapper per
method”, which is only a slight improvement.

Try to centralize access to the DB. Channel all method calls to the DB
through one dedicated method that handles db errors. something like
this could do the job:

class DB
def safe_call( method, *args, &block)
self.send( method, *args, &block)
rescue DBError

all db errorhandling here

end
end

there might be even better solutions

– meinrad

[email protected] wrote:

problem is that my application quits, since the application “run”

That’s a good question.

I usually just try to make “one rescue per method” as painless as
possible, by writing wrapper methods. Still, that’s “one wrapper per
method”, which is only a slight improvement.

Hi everyone,

Lyle, do you think it would be possible to add this feature to the FXApp
class: the ability to register some sort of “rescue handler”, that can
intercept in the “run” method the exceptions that would otherwise crash
the application? For compatitility, the default handler could simply
raise the exception again, which is what the framework is doing now.

This would be really useful.

Regards,

Philippe L.

On Oct 9, 2007, at 9:51 AM, Philippe L. wrote:

Lyle, do you think it would be possible to add this feature to the
FXApp
class: the ability to register some sort of “rescue handler”, that can
intercept in the “run” method the exceptions that would otherwise
crash
the application? For compatitility, the default handler could simply
raise the exception again, which is what the framework is doing now.

If you will file a bug report (or feature request) about it, I’ll
consider it. I know that it’s sometimes difficult to work around
FOX’s error handling mechanisms, since Jeroen just calls exit() on
most errors; but particular circumstance may not be affected by that.

[email protected] wrote:

If you will file a bug report (or feature request) about it, I’ll

begin
app.run
rescue => ex
if … # ex can be retried
retry
end
end
app.exit

Hi Joel,

This is exactly the kind of thing I was takling about, yes, and it works
pretty well, but not 100%, apparently. I’m not sure an FXApp can be
“re-run” that way, without taking risks. Is that true Joeroen?

In my tests, I have noticed for example that an FXTabBook, after an
exception caught by your technique, has got “zombie” pages in it: the
place is still allocated for a page tab, but no page tab is visible at
all.

I also tried that, but without success:

begin
  app.repaint
  app.forceRefresh
  app.flush
  app.run
rescue Exception => e
  ---> show error to the user
  retry
end
app.exit

Philippe

Philippe L. wrote:

[email protected] wrote:
,

Hi Joel,

This is exactly the kind of thing I was takling about, yes, and it works
pretty well, but not 100%, apparently. I’m not sure an FXApp can be
“re-run” that way, without taking risks. Is that true Joeroen?

In my tests, I have noticed for example that an FXTabBook, after an
exception caught by your technique, has got “zombie” pages in it: the
place is still allocated for a page tab, but no page tab is visible at
all.

The reason I thought it should work is that FXApp::run() and
FXApp::runWhileEvents() are doing basically the same thing, with
slightly different logic. So if it is safe to unwind from runWhileEvents
and then re-enter the event loop, then it should be safe to do so with
run as well.

Lyle J. wrote:

If you will file a bug report (or feature request) about it, I’ll
consider it. I know that it’s sometimes difficult to work around
FOX’s error handling mechanisms, since Jeroen just calls exit() on
most errors; but particular circumstance may not be affected by that.

I don’t think Philippe is talking about those kinds of situations (that
cause Fox to call exit()), but rather situations where ruby callback
raises a ruby exception, and it propagates outside of the #run call.

Is there any reason why the following code won’t work?

begin
app.run
rescue => ex
if … # ex can be retried
retry
end
end
app.exit

On 10/10/07, Joel VanderWerf [email protected] wrote:

 end

exception caught by your technique, has got “zombie” pages in it: the
place is still allocated for a page tab, but no page tab is visible at
all.

The reason I thought it should work is that FXApp::run() and
FXApp::runWhileEvents() are doing basically the same thing, with
slightly different logic. So if it is safe to unwind from runWhileEvents
and then re-enter the event loop, then it should be safe to do so with
run as well.

… if there weren’t all those nasty side effects :stuck_out_tongue:

[email protected] wrote:

The reason I thought it should work is that FXApp::run() and
FXApp::runWhileEvents() are doing basically the same thing, with
slightly different logic. So if it is safe to unwind from
runWhileEvents and then re-enter the event loop, then it should be
safe to do so with run as well.

OK, I managed to reduce my problem to the following test program: as
soon as you try to add a “buggy tab”, the GUI starts to mess up. The
result, you will see, is different if you start by adding a buggy tab,
or if you start by adding a normal tab.

Maybe I need to call some kind of “refresh” after the exception is
raised?


#!/usr/bin/ruby

require ‘fox16’

include Fox

class MyFXTabItem < FXTabItem

end

class MyBuggyFXTabItem < FXTabItem
def initialize(text, icon=nil, data=nil)
super
raise Exception.new
end
end

class MyWindow < FXMainWindow

def initialize(app)

super(app, "Window", nil, nil, DECOR_ALL, 0, 0, 600, 350)

# Menu bar stretched along the top of the main window
menubar = FXMenuBar.new(self, LAYOUT_SIDE_TOP|LAYOUT_FILL_X)

# File menu
filemenu = FXMenuPane.new(self)
FXMenuTitle.new(menubar, "&File", nil, filemenu)
FXMenuCommand.new(filemenu, "&Quit\tCtl-Q\tQuit the application",
    nil, app, FXApp::ID_QUIT)

# Content
contents = FXVerticalFrame.new(self, LAYOUT_FILL_X|LAYOUT_FILL_Y)

# Tabs
@tabbook = FXTabBook.new(contents,:opts =>

LAYOUT_FILL_X|LAYOUT_FILL_Y|LAYOUT_RIGHT)

FXButton.new(contents, "add tab").connect(SEL_COMMAND) do |sender,

selector, data|
# First item is a list
tab = MyFXTabItem.new(@tabbook, “&Simple List”, nil)
frame = FXHorizontalFrame.new(@tabbook,
FRAME_THICK|FRAME_RAISED)
simplelist = FXList.new(frame, :opts =>
LIST_EXTENDEDSELECT|LAYOUT_FILL_X|LAYOUT_FILL_Y)
simplelist.appendItem(“First Entry”)
simplelist.appendItem(“Second Entry”)
simplelist.appendItem(“Third Entry”)
simplelist.appendItem(“Fourth Entry”)

  frame.create
  tab.create
  tab.show

end

FXButton.new(contents, “add buggy tab”).connect(SEL_COMMAND) do
|sender, selector, data|
# Second item is a file list
tab = MyBuggyFXTabItem.new(@tabbook, “F&ile List”, nil)
frame = FXHorizontalFrame.new(@tabbook,
FRAME_THICK|FRAME_RAISED)
filelist = FXFileList.new(frame, :opts =>
ICONLIST_EXTENDEDSELECT|LAYOUT_FILL_X|LAYOUT_FILL_Y)

  frame.create
  tab.create
  tab.show

end

end

def create
super
show(PLACEMENT_SCREEN)
end

end

if FILE == $0

$app = FXApp.new(“Attik System”, “FXRuby Test”)
MyWindow.new($app)
$app.create

begin
$app.run
rescue Exception => e
FXMessageBox.information($app, MBOX_OK, “Error”, “An exception was
raised”)
retry
end
end