I reported this as bug #1724347, but it seems like the bug-list is less active than the forum list, so I'll repost it here just in case someone has an idea to help me. I have a ruby defined GObject that is a singleton and is "alive" as long as the Application is running. This GObject represents the state of a machine. I use several views defined in glade so the user can get different views of the machine depending on their interest.The views are loaded with libglade then "filled" with several controls programatically. This controls have to update their values when the GObject emits signals.So far so good, I've set this up and it works well. The problem is that when I destroy a view, the GRClosure for the signal keeps around since it is attached to the main GObject (the one representing the state of the machine) and even doing a signal_disconnect_handler will not free it. Since the callback has to reference the view, that means that the view doesn't get garbage collected leading to a seious memory leak wich I see no way to avoid. The reasonable behaviour would be to dettach the callback from the GObject once it has been disconnected. Attached to the bug report is a simple test that reproduces the bug. Cheers, (and thanks for your incredible work) V. Segui
on 2007-06-19 08:27
on 2007-06-19 08:29
Sorry, I forgot to mention that I can reproduce the bug with ruby-gnome-0.16 and ruby-gnome-0.14. Ruby versions tested are ruby-1.8.4 and ruby-1.8.5. Cheers V. Segui
on 2007-06-19 12:29
Hi, In <0fdafb3f83a88ea37349cc9bed06cb61@ruby-forum.com> "[ruby-gnome2-devel-en] Signal handling causes memory leaks" on Tue, 19 Jun 2007 08:27:09 +0200, Vicent Segui <ruby-forum-incoming@andreas-s.net> wrote: > callback from the GObject once it has been disconnected. > > Attached to the bug report is a simple test that reproduces the bug. I don't think it's not a memory leak. Could you add the following code to your sample script and try again? p :finished leaked_objects = Array.new 11.times{ |i| hash_objects=Hash.new{|h,k|h[k]=0} GC.start ObjectSpace.each_object{|obj| hash_objects[obj.class]+=1 } leaked_objects<<hash_objects if i==0 or i==10 } leaked_objects.each_with_index{|h,i| puts "LEAKED OBJECTS #{i}" h2 = leaked_objects[i+1] h2 = Hash.new{|h,k|h[k]=0} if not h2 h.each_pair{|k,v| puts "Leaked #{k}: #{h2[k]-v}" if (h2[k]-v)>0 } h2.each_pair{|k,v| puts "Leakdes #{k}: #{v-h[k]}" if (h[k] == 0) && (v != 0) } } Thanks, -- kou ------------------------------------------------------------------------- This SF.net email is sponsored by DB2 Express Download DB2 Express C - the FREE version of DB2 express and take control of your XML. No limits. Just data. Click to get it now. http://sourceforge.net/powerbar/db2/
on 2007-06-19 13:09
Hi kou, Thanks for your quick reply. I'm a little confused at what you are trying here, so where do you want me to add the above code? Should I delete my own code? I actually just added it yo my own code so correct me if I'm wrong. Here are my results: LEAKED OBJECTS 0 Leaked Hash: 12 Leaked Gtk::VBox: 10 Leaked String: 19 Leaked Proc: 12 Leaked Data: 10 Leaked Array: 10 LEAKED OBJECTS 1 :finished LEAKED OBJECTS 0 Leaked Proc: 1 LEAKED OBJECTS 1 Again, thanks for your quick reply, Cheers, V. Segui
on 2007-06-19 14:05
Hi, In <eb5a63bf9184fca37dee598bd619c972@ruby-forum.com> "Re: [ruby-gnome2-devel-en] Signal handling causes memory leaks" on Tue, 19 Jun 2007 13:09:13 +0200, Vicent Segui <ruby-forum-incoming@andreas-s.net> wrote: > Thanks for your quick reply. I'm a little confused at what you are > trying here, so where do you want me to add the above code? Should I > delete my own code? I actually just added it yo my own code so correct > me if I'm wrong. Here are my results: I wanted to show your test script doesn't show what you want to show. Could you rewrite a test script? The test script will have a GObject and some GtkWidgets. And the GtkWidgets will create and destroy many times. And then (or each time) your test script will report alive objects. Thanks, -- kou ------------------------------------------------------------------------- This SF.net email is sponsored by DB2 Express Download DB2 Express C - the FREE version of DB2 express and take control of your XML. No limits. Just data. Click to get it now. http://sourceforge.net/powerbar/db2/
on 2007-06-19 15:24
> I wanted to show your test script doesn't show what you want > to show. > > Thanks, > -- > kou > Hi Kou, I think the script does show a problem, the point is that if I comment the signal_connection code , that is if the following code is commented: #if we comment this we won't get the leakage id_signal = self.signal_connect("test") { |gobj| box.add Gtk::Label.new("Test") } #now disconnect the signals if not needed @window.signal_connect("destroy") { |win| self.signal_handler_disconnect(id_signal)if id_signal } then there is no "memory leak": LEAKED OBJECTS 0 Leaked Hash: 2 Leaked Proc: 2 LEAKED OBJECTS 1 :finished LEAKED OBJECTS 0 Leaked Proc: 1 LEAKED OBJECTS 1 I assume you mean that my script isn't accurate measuring the memory leak, which is true, but I have observed the "leak" acting in my app and it disappears if I comment the signal connection code. > Could you rewrite a test script? The test script > will have a GObject and some GtkWidgets. And the GtkWidgets > will create and destroy many times. And then (or each time) > your test script will report alive objects. > This is basically what I'm doing, I create the view every time, and then record the alive objects. At the end, I calculate the difference between the live objects at the beginning and those at the end of the iterations (the code is horrible, I know, but then I was in a hurry) and print that. The only relevant objects are those of the Gtk hierarchy of course, since ruby may be doing it's own stuff in the meantime. If you still need another test, please let me know, and I will see what I can bake up... Cheers, V. Segui
on 2007-06-19 15:44
Hikou,
I just noticed the following when using the test. If I create a
Gtk::Button and assign it to a var, it will "leak", even if i don't add
it to the box. If I just create the GtkButton but don't assign it it wil
not "leak". The only reason I can see for this behaviour is because the
GRClosure we create below for the signal captures it in its lexical
scope.
box = Gtk::VBox.new(2)
button = Gtk::Button.new()
@window.add box
id_signal = nil
#when we create this closure we capture the button
# and it leaks since the closure is not released even
# when disconnected
id_signal = self.signal_connect("test") { |gobj|
box.add Gtk::Label.new("Test")
}
Cheers,
V. Segui
on 2007-06-19 18:48
Hi Vicent, I don't know what is the correct result by your test_signal_disconnection.rb. My result was: ---- LEAKED OBJECTS 0 Leaked Hash: 2 Leaked Proc: 2 Leaked Data: 10 Leaked Array: 1 LEAKED OBJECTS 1 ---- Where is the point ? Do you mean there are 15(2+2+10+1) objects leaked? Should all lines be 0 ? On Tue, 19 Jun 2007 08:27:09 +0200 Vicent Segui <ruby-forum-incoming@andreas-s.net> wrote: > their interest.The views are loaded with libglade > not free it. Since the callback has to reference the view, that means > > ruby-gnome2-devel-en@lists.sourceforge.net > https://lists.sourceforge.net/lists/listinfo/ruby-gnome2-devel-en > ------------------------------------------------------------------------- This SF.net email is sponsored by DB2 Express Download DB2 Express C - the FREE version of DB2 express and take control of your XML. No limits. Just data. Click to get it now. http://sourceforge.net/powerbar/db2/
on 2007-06-19 23:12
> Where is the point ? > Do you mean there are 15(2+2+10+1) objects leaked? > Should all lines be 0 ? > Hi Masao, All lines need not be 0 (we have to consider for the "leak detection" algorithim's own memory use), but I should not have Gtk objects printed (which I do) there since they should be created and destroyed properly. Unfortunately, after I run test_signal_connection.rb, with the signal connection code uncommented, I get 10 Gtk::Boxes or whatever Gtk object I create and assign to a variable in the lexical scope of the signal closure. The only reason for this is that a) we are not properly releasing the GRClosure b) We do release the GRClosure but this one somehow does not release it's "links" to the variables c) There is something wrong in my "leak" detection algorithm wich only manifests itself when I do the signal_connect stuff. However, please note that running that code enough times will actually see a real increment in memory use as measured by top. Thank you for your time, cheers, V. Segui
on 2007-06-20 17:33
Hi, On Tue, 19 Jun 2007 23:12:31 +0200 Guest <ruby-forum-incoming@andreas-s.net> wrote: > I create and assign to a variable in the lexical scope of the signal > closure. The only reason for this is that > > a) we are not properly releasing the GRClosure > b) We do release the GRClosure but this one somehow does not release > it's "links" to the variables > c) There is something wrong in my "leak" detection algorithm wich only > manifests itself when I do the signal_connect stuff. However, please > note that running that code enough times will actually see a real > increment in memory use as measured by top. For understanding, I need to try to reproduce your problem easier. So I wrote 2 small samples. (1) --------------------- require 'gtk2' def test a = Gtk::Button.new handler_id = a.signal_connect("clicked"){1 + 1} # a.signal_handler_disconnect(handler_id) # a.destroy end loop { test GC.start } --------------------- (2) --------------------- require 'gtk2' def test a = Gtk::Button.new a.signal_connect("clicked"){ 1 + 1 } # a.signal_handler_disconnect(handler_id) # a.destroy end 10000.times { test } GC.start objs = [] ObjectSpace.each_object(GLib::Object){|obj| objs << obj } p objs --------------------- I test (1) with "top" command, but it doesn't seem to leak memory. Then I test (2), the result was: [#<Gtk::Button:0x2aaaafdad2a0 ptr=0xd79800>] Actually there is an object which is not released yet, but I think this is not your problem. % ruby -v -rgtk2 -W0 -e 'p Gtk::BINDING_VERSION' ruby 1.8.6 (2007-03-13 patchlevel 0) [x86_64-linux] [0, 16, 0] ------------------------------------------------------------------------- This SF.net email is sponsored by DB2 Express Download DB2 Express C - the FREE version of DB2 express and take control of your XML. No limits. Just data. Click to get it now. http://sourceforge.net/powerbar/db2/
on 2007-06-21 08:47
Hi Masao Mutoh, > Actually there is an object which is not released yet, > but I think this is not your problem. > Thank you for your reply. Actually the problem is related, try with this code: 1) require 'gtk2' def test(obj) a = Gtk::Button.new handler_id = obj.signal_connect("clicked"){ 1 + 1 } obj.signal_handler_disconnect(handler_id) a.destroy end obj = Gtk::Button.new 10000.times { test(obj) } GC.start objs = [] ObjectSpace.each_object(GLib::Object){|obj| objs << obj } p objs In my machine it will print thousands of Gtk::Buttons that are Glib::destroyed but not GC. My guess is that this is probably because the closure created with obj.signal_connect still has a reference to the Buttons and it isn't realeasing it, even if we disconnect it. You can test it by commenting the signal_comment code like this: 2) def test(obj) a = Gtk::Button.new # handler_id = obj.signal_connect("clicked"){ 1 + 1 } # obj.signal_handler_disconnect(handler_id) a.destroy end obj = Gtk::Button.new 10000.times { test(obj) } GC.start objs = [] ObjectSpace.each_object(GLib::Object){|obj| objs << obj } p objs and it will print: [#<Gtk::Button:0xb6a9b904 destroyed>, #<Gtk::Button:0xb6b0780c ptr=0x8280510>] instead of the thousand instances of #<Gtk::Button:0xb6a9b904 destroyed> it prints when 1) is run. I hope this clarifies my issue better. thanks for your time, cheers, V. Segui
on 2007-06-21 16:45
Hi, From: Vicent Segui <ruby-forum-incoming@andreas-s.net> Date: Thu, 21 Jun 2007 08:47:08 +0200 > In my machine it will print thousands of Gtk::Buttons that are > Glib::destroyed but not GC. My guess is that this is probably because > the closure created with obj.signal_connect still has a reference to the > Buttons and it isn't realeasing it, even if we disconnect it. Your guess is correct. obj still has a reference to the signal handler even after we disconnect it. Then the Button is also refered by obj via the signal handler's Proc object. Here is a makeshift patch against ruby-gnome2-0.16 that fix this problem partially. --- rbgobj_closure.c.orig 2006-12-29 22:17:29.000000000 +0900 +++ rbgobj_closure.c 2007-06-21 22:55:47.000000000 +0900 @@ -243,8 +243,10 @@ rclosure_unref(GRClosure *rclosure) if (!rclosure_alive_p(rclosure)) { GList *next; for (next = rclosure->objects; next; next = next->next) { - GObject *object; - object = G_OBJECT(next->data); + GObject *object = G_OBJECT(next->data); + VALUE obj = rbgobj_ruby_object_from_instance2(object, FALSE); + if (!NIL_P(rclosure->rb_holder) && !NIL_P(obj)) + G_CHILD_REMOVE(obj, rclosure->rb_holder); g_object_weak_unref(object, rclosure_weak_notify, rclosure); } g_list_free(rclosure->objects); -- Masahiro Sakai ------------------------------------------------------------------------- This SF.net email is sponsored by DB2 Express Download DB2 Express C - the FREE version of DB2 express and take control of your XML. No limits. Just data. Click to get it now. http://sourceforge.net/powerbar/db2/
on 2007-06-21 16:54
Masahiro Sakai wrote: > Hi, > > From: Vicent Segui <ruby-forum-incoming@andreas-s.net> > Date: Thu, 21 Jun 2007 08:47:08 +0200 > >> In my machine it will print thousands of Gtk::Buttons that are >> Glib::destroyed but not GC. My guess is that this is probably because >> the closure created with obj.signal_connect still has a reference to the >> Buttons and it isn't realeasing it, even if we disconnect it. > > Your guess is correct. > obj still has a reference to the signal handler even after we > disconnect it. Then the Button is also refered by obj via the signal > handler's Proc object. > > Here is a makeshift patch against ruby-gnome2-0.16 that fix this > problem partially. > > --- rbgobj_closure.c.orig 2006-12-29 22:17:29.000000000 +0900 > +++ rbgobj_closure.c 2007-06-21 22:55:47.000000000 +0900 > @@ -243,8 +243,10 @@ rclosure_unref(GRClosure *rclosure) > if (!rclosure_alive_p(rclosure)) { > GList *next; > for (next = rclosure->objects; next; next = next->next) { > - GObject *object; > - object = G_OBJECT(next->data); > + GObject *object = G_OBJECT(next->data); > + VALUE obj = rbgobj_ruby_object_from_instance2(object, > FALSE); > + if (!NIL_P(rclosure->rb_holder) && !NIL_P(obj)) > + G_CHILD_REMOVE(obj, rclosure->rb_holder); > g_object_weak_unref(object, rclosure_weak_notify, > rclosure); > } > g_list_free(rclosure->objects); > > -- Masahiro Sakai > > ------------------------------------------------------------------------- > This SF.net email is sponsored by DB2 Express > Download DB2 Express C - the FREE version of DB2 express and take > control of your XML. No limits. Just data. Click to get it now. > http://sourceforge.net/powerbar/db2/ Hi Masao, Thanks a lot for the patch. I know things have changed a lot since ruby-gnome 0.14 but will this patch also apply there? At the moment I can't upgrade to 0.16 since I'm still getting hit ocasionally (which is why I haven't been able to reproduce a test case to report) with the "GRClosure already destroyed" (like in Bug #1637290) issue. Thanks a lot for looking in to this, V. Segui
on 2007-06-21 17:02
Hi Vicent, On Thu, 21 Jun 2007 16:54:39 +0200 Vicent Segui <ruby-forum-incoming@andreas-s.net> wrote: > > > > @@ -243,8 +243,10 @@ rclosure_unref(GRClosure *rclosure) > > g_object_weak_unref(object, rclosure_weak_notify, > > http://sourceforge.net/powerbar/db2/ > > > Hi Masao, Oops, Unfortunately, thie patch is Masahiro Sakai, not me. > Thanks a lot for the patch. I know things have changed a lot since > ruby-gnome 0.14 but will this patch also apply there? At the moment I > can't upgrade to 0.16 since I'm still getting hit ocasionally (which is > why I haven't been able to reproduce a test case to report) with the > "GRClosure already destroyed" (like in Bug #1637290) issue. Ruby-GNOME2 0.14.0 has other memory leaks problems and many bugs. I highly recommand to upgrade it to 0.16. ------------------------------------------------------------------------- This SF.net email is sponsored by DB2 Express Download DB2 Express C - the FREE version of DB2 express and take control of your XML. No limits. Just data. Click to get it now. http://sourceforge.net/powerbar/db2/
on 2007-06-21 17:03
Hi Sakai-san, Great! Could you apply this patch to CVS ? On Thu, 21 Jun 2007 23:42:34 +0900 (JST) Masahiro Sakai <sakai@tom.sfc.keio.ac.jp> wrote: > Your guess is correct. > if (!rclosure_alive_p(rclosure)) { > g_list_free(rclosure->objects); > ruby-gnome2-devel-en@lists.sourceforge.net > https://lists.sourceforge.net/lists/listinfo/ruby-gnome2-devel-en > ------------------------------------------------------------------------- This SF.net email is sponsored by DB2 Express Download DB2 Express C - the FREE version of DB2 express and take control of your XML. No limits. Just data. Click to get it now. http://sourceforge.net/powerbar/db2/
on 2007-06-21 17:28
Hi, On Thu, 21 Jun 2007 08:47:08 +0200 Vicent Segui <ruby-forum-incoming@andreas-s.net> wrote: > def test(obj) > objs = [] > ObjectSpace.each_object(GLib::Object){|obj| > objs << obj > } > p objs > > > In my machine it will print thousands of Gtk::Buttons that are > Glib::destroyed but not GC. My guess is that this is probably because > the closure created with obj.signal_connect still has a reference to the > Buttons and it isn't realeasing it, even if we disconnect it. Hmm, unless Masahiro's patch, it printed: [#<Gtk::Button:0x2aaaafe04550 destroyed>, #<Gtk::Button:0x2aaaafe40cf8 ptr=0x917830>] Of course it's on 0.16.0. This result is the same with Masahiro's patch. I think Masahiro's patch makes the thing better, but there are other problems on 0.14.0 which have been fixed until 0.16.0. ------------------------------------------------------------------------- This SF.net email is sponsored by DB2 Express Download DB2 Express C - the FREE version of DB2 express and take control of your XML. No limits. Just data. Click to get it now. http://sourceforge.net/powerbar/db2/
on 2007-06-21 17:40
Masao Mutoh wrote: > > Of course it's on 0.16.0. This result is the same with Masahiro's patch. > Hi Masao, Sorry for the confusion :). Many thanks Sakai for the patch!. I've tried this with both ruby-gnome 0.16 and ruby-gnome 0.14 and both seem to leak (I haven't tried Sakai's patch still) can you confirm that you are running the testcase 1 of my previous post (the one with the signal_connect code *uncommented*)? Cheers, V. Segui > I think Masahiro's patch makes the thing better, but there are other > problems on 0.14.0 > which have been fixed until 0.16.0. > I've tried 0.16 but I get the dreaded "GRClosure already destroyed" bug. I will give a try to the CVS version (if I can't apply this patch to 0.14) ASAP and report. Many thanks to all of you, V. Segui
on 2007-06-21 18:32
Hi, On Thu, 21 Jun 2007 17:40:35 +0200 Vicent Segui <ruby-forum-incoming@andreas-s.net> wrote: > signal_connect code *uncommented*)? Oops. I was wrong. I tested the CVS version unless Masahiro's patch. On pure 0.16, the thousand Gtk::Button(destroyed) was remained. Sorry for confusing you. > I've tried 0.16 but I get the dreaded "GRClosure already destroyed" bug. > I will give a try to the CVS version (if I can't apply this patch to > 0.14) ASAP and report. Many thanks to all of you, I hope the latest version(CVS + Masahiro's patch) fix your problem. ------------------------------------------------------------------------- This SF.net email is sponsored by DB2 Express Download DB2 Express C - the FREE version of DB2 express and take control of your XML. No limits. Just data. Click to get it now. http://sourceforge.net/powerbar/db2/
on 2007-06-22 16:04
> > I hope the latest version(CVS + Masahiro's patch) fix your problem. > I still haven't tried CVS (it's blocked by the firewall :( ) but using the patch on pristine 0.16 will make it segfault ocasionally when doing test_signal_connect2.rb with the signal_connect uncommented. Just reporting in case you guys are interested. Will try to get the admin to open the firewall and try again. Cheers, V. SeguÃ
Please log in before posting. Registration is free and takes only a minute.
Existing account
(Switch to SSL-encrypted connection)
NEW: Do you have a Google/GoogleMail or Yahoo account? No registration required!
Log in with Google account | Log in with Yahoo account
Log in with Google account | Log in with Yahoo account
No account? Register here.