Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Exceptions inside of blocks #12

Open
JosephAustin opened this issue Oct 6, 2014 · 24 comments
Open

Exceptions inside of blocks #12

JosephAustin opened this issue Oct 6, 2014 · 24 comments

Comments

@JosephAustin
Copy link

In many cases it appears that exceptions getting thrown within a do block will cause the program to hang, instead of reporting the backtrace. It then continuously increases in memory use. The problem can also be triggered by using a rescue and trying to print out the exception's message, which leads me to think its message is either very large or generates recursively somehow.

ex:

      button "Purge", parent:packer do
        blah = not_existing_variable
        Dir.glob(File.join($window.trashFolder, "*.*")).each do |file|
          if(!File.directory? file)
            File.delete file
          end
        end
      end

The above code crashes like you would expect on that second line, but at that point the code totally freezes. If I print out its backtrace I get:

../lib/fidgit/event.rb:128:in `call'

../lib/fidgit/event.rb:128:in `block in publish'

../lib/fidgit/event.rb:127:in `reverse_each'

../lib/fidgit/event.rb:127:in `publish'

../lib/fidgit/states/gui_state.rb:284:in `redirect_released_mouse_button'

etc...

Seems to me that something goes totally batty in the event handling. I'm on x86-64 Linux using Ruby 2.1.2p95

EDIT

The issue appears to be caused by the destruction order of widgets in any sort of list. An empty list finishes faster, but the problem is exponential. Manually catching issues inside of event blocks and clearing the list widgets with @widget.parent.clear and then setting the widget itself to nil immediately works, and the error can then be thrown. This provides a troublesome but functional work-around.

@bil-bas
Copy link
Collaborator

bil-bas commented Oct 6, 2014

Does the exception handling work with 1.9.3 or not? (That is the last version I tested it on). I do some funky stuff to make those blocks work, which may possibly be fubar in newer versions.

@JosephAustin
Copy link
Author

Hmm, not sure. I will make an attempt. I'm guessing it will and that'll turn out to be what happened. I'll have to roll back somehow or other.

@bil-bas
Copy link
Collaborator

bil-bas commented Oct 6, 2014

I really don't know myself. It is still reasonably likely to be a fault in fidgit, rather than something that went "wrong" with Ruby since I wrote it.

@JosephAustin
Copy link
Author

Building it now. Well, you know how it goes, something could have gone 'right' in Ruby since you wrote it that turned what you did wrong :P These things happen.

@bil-bas
Copy link
Collaborator

bil-bas commented Oct 6, 2014

Aye! That is probably the case 😊

@bil-bas
Copy link
Collaborator

bil-bas commented Oct 6, 2014

As an aside, the Ruby idiom is:

File.delete file unless File.directory? file

@JosephAustin
Copy link
Author

Yes, I'm still learning ;) Ive been doing that more often now.

I just fired up 1.9.3's irb and got my app to load up, and it handles the exceptions. so there we go.

@bil-bas
Copy link
Collaborator

bil-bas commented Oct 7, 2014

Well, that is "good" news, though I have no idea why it shouldn't work on 2.1 (I haven't used 2.0+ very much at all).

p.s. Drop IRB and start using Pry instead ;)

@bil-bas
Copy link
Collaborator

bil-bas commented Oct 7, 2014

I'm presuming that https://github.com/Spooner/fidgit/blob/master/lib/fidgit/redirector.rb is what is faulty, which is what is used to create those "clever" blocks (in a really dumb way). Might be obvious what is wrong if I knew anything about the newer Ruby versions.

@JosephAustin
Copy link
Author

Okay then, I'll have a look at it and if I fix it I'll send you a patch :) There's a workaround by doing exception handling inside every block manually

@bil-bas
Copy link
Collaborator

bil-bas commented Oct 7, 2014

Another workaround would be to not use the blocks (they just make things easier) 😛

@JosephAustin
Copy link
Author

And i was wrong, i corrected myself and it -does- lock up in the older ruby. It says

"NameError:"

and freezes.

@JosephAustin
Copy link
Author

And then the memory use goes up, up , up.... ctrl-c gives me the proper dump. So some recursive or infinite loop happens.

@bil-bas
Copy link
Collaborator

bil-bas commented Oct 7, 2014

Hmm - do you have a full chunk of code that fails in this way that you could show me? Not sure I'd have any luck, but I can take a look.

@JosephAustin
Copy link
Author

Hrm. It's something I did because i just tried to recreate the issue from scratch and couldn't. I would guess it has to do with all the threading stuff i have going on. This simple snippet:

require 'fidgit'

class TestState < Fidgit::GuiState
def initialize
super

horizontal do
  vertical do |packer|
    button "Test", parent:packer do
      hdkjshfk = djxhf
    end
  end
end

end
end

class Window < Chingu::Window
def initialize
super 800, 600, false
push_game_state TestState
end
end

$Window = Window.new
$Window.show

works fine

@JosephAustin
Copy link
Author

ugh, that formatted nicely.

@bil-bas
Copy link
Collaborator

bil-bas commented Oct 7, 2014

Fidgit is definitely not thread-safe code.

@JosephAustin
Copy link
Author

Yeah but it's not running any of that in an actual thread, i just happen to have a few running off to the side loading thumbnails. Okay, I'm going to just say don't sweat it for now. If I figure out a specific cause I'll let you know.

@bil-bas
Copy link
Collaborator

bil-bas commented Oct 7, 2014

I'd recommend you use fibers rather than Threads anyway (except if there is blocking, such as in sockets, and then there are managed ways to manage that so you shouldn't ever need threads).

@JosephAustin
Copy link
Author

Oh, I didn't know about these. They look like c# coroutines. Thanks!

@bil-bas
Copy link
Collaborator

bil-bas commented Oct 7, 2014

Yes, very similar I think. Saves on a lot of the horrors of manual thread usage ;) Best of luck!

@JosephAustin
Copy link
Author

Found it. It has something to do with having a file list. I copied mine from your default and modified it, but even yours causes the bug. Here's the code:

http://pastebin.com/9N4HsfBg

Now you can see. Changing File Dialog to File Browser has the same effect

@JosephAustin
Copy link
Author

Well I'm off for now. I'll keep poking, but it looks like it has to do with the presence of a list. When I deleted everything but the list it still hung, but for an even more negligible amount of time. It probably has something to do with recursively cleaning up the list and the associated event handlers.

It's interesting that if you rescue from where the issue happens and raise 'messed up' instead, it crashes smoothly, but if you do a rescue => e and then puts e, you get the same issue on the print statement. Wild.

I'm going to go wander the Mojave wasteland now.

@JosephAustin
Copy link
Author

Okay, got a workaround:

      button "Purge", parent:packer do
        begin
          jkh = hjh
          Dir.glob(File.join($window.trashFolder, "*.*")).each do |file|
            File.delete file unless File.directory? file
          end
        rescue => y
          @folderBrowser.parent.clear
          @folderBrowser = nil
          raise y
        end
      end

This causes an immediate crash... as it ought. As long as the list is manually removed from the system and destroyed before raising the issue, it works.

So the 'message' of the exception is not problematic, but when it is requested, it seems that Ruby wants to finishes destructing everything first, and somehow lists make this an exponentially larger process, so it hangs. GC.start doesn't do it, so it isn't the collector.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants