From: Kevin B. <kev...@sy...> - 2003-09-29 19:28:21
|
To All, I'm having a problem with using descedants of FXTreeItem. Whatever is causing the problem is hosing FXTreeList::removeItem. Environment: ruby 1.8.0 (2003-09-29) [i686-linux] (though I've used several 1.8 versions) fox 1.0.46 FXRuby 1.0.26 Source that causes the bug is at the end of this message. The problem appears in FXTreeList::removeItem, whenever a child item has focus: // Deleted current item if(currentitem && item==olditem){ if(hasFocus()){ currentitem->setFocus(TRUE); } if((options&SELECT_MASK)==TREELIST_BROWSESELECT && currentitem->isEnabled()){ selectItem(currentitem,notify); } } currentItem->setFocus ends up calling an already destroyed object or something. I traced which pointers were being freed, and it looked okay, so I'm not sure what's going on. I'm guessing that memory is getting trashed. Any help on this would be appreciated. I'm trying to get a ruby/fox/FXRuby app completed very quickly. My workaround right now is to change the focus to another control in onCmdQuit. Kevin ------------------------- require 'fox' include Fox class MyTreeItem < FXTreeItem end class MyMainWindow < FXMainWindow def initialize(app) super(app, 'Bug', nil, nil, DECOR_ALL, 0, 0, 600, 400) tree = FXTreeList.new(self, 0, nil, 0, TREELIST_NORMAL|TREELIST_SHOWS_LINES|TREELIST_SHOWS_BOXES|TREELIST_ROOT_BOXES|LAYOUT_FILL_X|LAYOUT_FILL_Y) item = tree.addItemLast(@tree, MyTreeItem.new('Select and close - just fine')) item = tree.addItemLast(item, MyTreeItem.new('Select and close - choke')) end def create super show(PLACEMENT_SCREEN) end end app = FXApp.new('bug', 'bugtest') MyMainWindow.new(app) app.create app.run |
From: Joel V. <vj...@PA...> - 2003-09-29 21:19:50
|
Kevin Burge wrote: > To All, > > I'm having a problem with using descedants of FXTreeItem. Whatever is > causing the problem is hosing FXTreeList::removeItem. I think that's the same bug that I reported here about a month ago, but couldn't isolate very well. Attached is Lyle's response. In my case also, selecting a root node avoids the segfault, while selecting a child causes the segfault. Also, I am subclassing FXTreeItem, so it seems quite possibly the same bug. Another thing that might confirm: Ctrl-Q and Alt-F4 both cause the segfault Alt-F-Q and File->Quit do not Does this happen for you, Kevin? All my Quit command does is getApp().exit. |
From: Lyle J. <jl...@cf...> - 2003-09-30 14:31:53
|
Joel VanderWerf wrote: > > Kevin Burge wrote: > >> To All, >> >> I'm having a problem with using descedants of FXTreeItem. Whatever is >> causing the problem is hosing FXTreeList::removeItem. > > > I think that's the same bug that I reported here about a month ago, but > couldn't isolate very well. Guys, Sorry I didn't respond sooner, but I have been sick the last few days. I have only started looking at the problem again this morning, but have already found one interesting thread to follow. Since both of you were using custom subclasses of FXTreeItem, I tried replacing the MyTreeItem instances in Kevin's example with regular tree items, i.e. item = tree.addItemLast(@tree, FXTreeItem.new("... just fine")) item = tree.addItemLast(item, FXTreeItem.new("... choke")) The program still crashes as before. Next, I tried using the other overload of FXTreeList#addItemLast, i.e. item = tree.addItemLast(@tree, "... just fine") item = tree.addItemLast(item, "... choke") and this version does *not* crash. This suggests (at least) a couple of possibilities that I need to investigate. Will let you know as soon as I have something for you. Thanks for your patience, Lyle |
From: Kevin B. <kev...@sy...> - 2003-09-30 15:10:55
|
Just did some more testing based on this response: On Tue, 2003-09-30 at 09:47, Lyle Johnson wrote: > Guys, > > Next, I tried using the other > overload of FXTreeList#addItemLast, i.e. > > item = tree.addItemLast(@tree, "... just fine") > item = tree.addItemLast(item, "... choke") > > and this version does *not* crash. This suggests (at least) a couple of > possibilities that I need to investigate. Will let you know as soon as I > have something for you. It ONLY fails if the item selected is a DIRECT subitem of an item added with addItemList(nil, FXTreeItem.new(...)). I.e.: item = tree.addItemLast(nil, '... just fine') item = tree.addItemLast(item, FXTreeItem.new('... just fine')) item = tree.addItemLast(item, '... choke') item = tree.addItemLast(item, '... just fine') Hope that helps! Kevin |
From: Joel V. <vj...@PA...> - 2003-09-29 21:27:37
Attachments:
Attached Message
|
Joel VanderWerf wrote: > I think that's the same bug that I reported here about a month ago, but > couldn't isolate very well. Attached is Lyle's response. Well, now it is :) |
From: Kevin B. <kev...@sy...> - 2003-09-29 21:43:16
|
Joel, Thanks for the response. Definitely sounds like the same problem. Possible reason that Ctrl-Q and File->Quit act differently: the tree no longer has the focus. It ONLY happens when the tree has the focus and a subitem is selected. FWIW, I also have developed a Ruby extension (for commerical use). I believe there is some kind of bug in Ruby 1.8's cleanup that causes an infinite loop whenever you try to use rb_io_write (via rb_warn, etc.) when ruby_finalize_0 has been called, which FXRuby also encounters after the bad call to SetFocus. I haven't been able to isolate that, but, it sure does make finding the actual cause of the MY (and FXRuby's problem) more difficult. I ran into this problem because memory was being trashed (because I was not forcing my objects to clean up orderly, no matter what object the GC cleaned up first.) Kevin On Mon, 2003-09-29 at 16:27, Joel VanderWerf wrote: > Joel VanderWerf wrote: > > > I think that's the same bug that I reported here about a month ago, but > > couldn't isolate very well. Attached is Lyle's response. > > Well, now it is :) > > ______________________________________________________________________ |
From: Lyle J. <jl...@cf...> - 2003-09-30 16:54:53
|
Kevin Burge wrote: > It ONLY fails if the item selected is a DIRECT subitem of an item added > with addItemList(nil, FXTreeItem.new(...)). Yes, it turns out that this is just a symptom of a more general problem. I think I have identified the basic problem and so now I need to decide what is the best solution (decision-making currently in progress ;) The problem is that when the Ruby interpreter shuts down, it finalizes all of the still-alive objects in a more or less random order. In our case, it is first finalizing the two tree items, and later the tree list itself. At the time the tree items are finalized in the Ruby interpreter, Ruby doesn't "own" the underlying C++ FXTreeItem objects and thus doesn't have permission to call the C++ objects' destructors. This situation is correctly accounted for in the FXRuby GC code; the Ruby instances go away, but the C++ objects hang around. It's not a memory leak since the FXTreeList owns those two tree item objects and will dispose of them later, when it is destroyed. So far, so good. Time passes, and now it's time to finalize the tree list in the Ruby interpreter. As you have perhaps seen in the FOX source code, the main business of FXTreeList's destructor is to recursively destroy all of its tree items in a sort of depth-first manner. So it burrows down and deletes the lowest-level tree item. And since that item was the current item and had the focus, FOX wants to transfer the focus to the new current item, namely, the root-level item. It does so by calling the root item's virtual setFocus() member function, and that's where the trouble starts. Since setFocus() is a virtual C++ member function, and since it is possible that you (the application writer) have overridden that virtual function in your Ruby code, we look up the Ruby instance associated with this C++ FXTreeItem object. You may recall that this Ruby object was finalized earlier and no longer exists, but we still find it in our map of C++ objects to Ruby objects, so FXRuby goes ahead and tries to invoke a method call (for the potentially-overridden setFocus) on it. This is where the seg fault occurs. The short synopsis of the solution is, "make sure that the link between the deceased Ruby object and the still-living C++ object gets broken at the right time", and I'm still trying to decide when that right time is. But I should be able to get a fix in the next day or so, at the latest. |
From: Kevin B. <kev...@sy...> - 2003-09-30 17:38:24
|
The short synopsis of the solution is, "make sure that the link between > the deceased Ruby object and the still-living C++ object gets broken at > the right time", and I'm still trying to decide when that right time is. > But I should be able to get a fix in the next day or so, at the latest. As I mentioned, I have written my own Ruby extension. I had (and am still having in one place) the same problem as FXRuby. The API I wrapped (manually, not with SWIG) does not keep track of object references (no parent->child connection, only child->parent), and expects the programmer to destroy objects in an orderly fashion. Of course, Ruby choked on this, since, as you said, at finalization, it destroys the objects (almost) randomly. My solution was to make all the objects remember each other, and whenever a child is destroy, it has the parent remove it from it's "children", and if the parent is destroyed it tells all the children to destroy themselves first. The difference from FXRuby is that I DESTROY the items, even though the Ruby object may still exist. The Ruby VALUEs outlive the C objects they point to, whereas in FXRuby, the C++ objects outlive their Ruby VALUEs. My reasoning was: as long as I have the marking right, I'll never have Ruby VALUEs pointing to uninitialized C objects. At finalization, the Ruby VALUEs will never be used again, so it doesn't matter at that point. Not fully comprehending the FXRuby internals (though I have looked at it quite a bit): What I think should happen is that any owned object must use it's "owner" to remove itself and/or unregister itself. I.e. in "delete_if_not_owned", there should be a call to "owner->remove(self)" just before FXRbUnregisterRubyObj. Said differently, if Ruby destroys an owned object, the owner should first UNOWN the object. So, in the case of the above: If 4 items are added as children of one another, and the first is freed by Ruby, it's freefunc should call the TreeList->removeItem(self) BEFORE it unregisters itself. This will remove all the children items (and their unregistering their Ruby objects), etc., etc. I'd help if I had time. Gotta finish my FXRuby app! :) Kevin |