Ruby Forum FXRuby > FXRuby default error handler

Posted by Philippe Lang (Guest)
on 08.10.2007 11:53
(Received via mailing list)
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 Lang
Posted by Joel VanderWerf (Guest)
on 08.10.2007 21:44
(Received via mailing list)
Philippe Lang 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.
Posted by Meinrad Recheis (Guest)
on 08.10.2007 22:56
(Received via mailing list)
On 10/8/07, Joel VanderWerf <vjoel@path.berkeley.edu> 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
Posted by Philippe Lang (Guest)
on 09.10.2007 16:51
(Received via mailing list)
fxruby-users-bounces@rubyforge.org 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 Lang
Posted by Lyle Johnson (Guest)
on 09.10.2007 18:27
(Received via mailing list)
On Oct 9, 2007, at 9:51 AM, Philippe Lang 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.
Posted by Joel VanderWerf (Guest)
on 09.10.2007 19:37
(Received via mailing list)
Lyle Johnson 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
Posted by Philippe Lang (Guest)
on 10.10.2007 17:33
(Received via mailing list)
fxruby-users-bounces@rubyforge.org 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
Posted by Joel VanderWerf (Guest)
on 10.10.2007 23:14
(Received via mailing list)
Philippe Lang wrote:
> fxruby-users-bounces@rubyforge.org 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.
Posted by Meinrad Recheis (Guest)
on 11.10.2007 09:48
(Received via mailing list)
On 10/10/07, Joel VanderWerf <vjoel@path.berkeley.edu> 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 :P
Posted by Philippe Lang (Guest)
on 11.10.2007 10:57
(Received via mailing list)
fxruby-users-bounces@rubyforge.org 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