How to track "GRClosure invoking callback:..." errors?

Hi,

This one is driving me crazy. I’m using ruby-gnome2 0.16.0 on an 32-bit
linux machine.

I’ve something like this
class TestTable
attr_accessor :content_types
attr_accessor :content_columns
attr_accessor :view
attr_accessor :liststore

def initialize
self.content_types = String, Integer, String, STring, String
self.content_columns = [“hmm”,“int”,“a”,“b”,“c”]

self.liststore = Gtk::ListStore.new(*self.content_types)
self.view = Gtk::TreeView.new(self.liststore)
self.liststore.signal_connect("sort-column-changed"){ |me|
  c_id, order = self.liststore.sort_column_id
  puts "sort column changed: #{c_id} #{order}"
}

end
end

The signal_connect(“sort-column-changed”) parts causes the headache. For
the first times it works, then I’ll get the warning
./start.rb:19: warning: GRClosure invoking callback: already destroyed
(line 19 in start.rb is Gtk.main )

I tracked down the problem to the Garbage collector. A GC.disable solves
this issue… but then my program dosen’t free memory anymore which is
not a good thing at all.

liststore is still there and liststore.sort_column_id is also updated.
So I guess the signal-connect block has been deleted by the GC?

I wanted to create a test-case. But strangely I cannot reproduce this
error in my test application which only removed my API part and
simplified some things.

Any advise how to debug this?

Hi,

could you post a (at least partial) working example, please.

Cheers, detlef

Am Samstag, den 01.03.2008, 23:17 +0100 schrieb Joachim G.:

Detlef R. wrote:

Hi,

could you post a (at least partial) working example, please.

Ah, yes. I could finally track the problem down and make a demo. See
attached file. Try changing the sort bars several time, in this test I
need between 15 and 30 clicks.

The problem is caused by this: I’m using custom classes for formatting
stuff, for example a Currency in a list, like this:

class EuroCurrency < Float

this seems cause the problem:

def self.fmt_str(text)
sprintf("%.2f",text.to_f).gsub(".",",")+" Euro"
end

end

At rendering I have this sniplet which calls the fmt_str method if this
one of my custom models:

if is_custom_class(i) == true
str_class = self.column_types[i]

that one seems to do the problem:

col.set_cell_data_func(renderer) do |col, renderer, model, iter|
renderer.text = str_class.fmt_str(renderer.text)
end
end

Hi,

i’ve reworked and simplified your example to this:

#!/usr/bin/ruby
require ‘gtk2’

module EuroCurrency
def fmt_str(text)
sprintf("%.2f",text.to_f).gsub(".",",")+" Euro"
end
module_function :fmt_str
end

class TestTable
def initialize
@column_types = String, String, String
@content_columns = [“str”, “str”, “cur”]

initialize table

@liststore = Gtk::ListStore.new(*@column_types)
@view = Gtk::TreeView.new(@liststore)
@liststore.signal_connect("sort-column-changed") do |me|
  c_id, order = @liststore.sort_column_id
  puts "sort column changed: #{c_id} #{order}"
end

end

def is_custom_class(i)
@content_columns[i] == “cur”
end

def add_row(data)
row = @liststore.append
i = 0
data.each do |d|
row[i] = d
i = i +1
end
end

def render_and_attach(widget)
i = 0
@content_columns.each do |name|
renderer = Gtk::CellRendererText.new
col = Gtk::TreeViewColumn.new(name, renderer, :text => i)
@view.append_column(col)
col.sort_column_id = i

  if is_custom_class(i)
    col.set_cell_data_func(renderer) do |col, renderer, model, iter|
      renderer.text = EuroCurrency.fmt_str(renderer.text)
    end
  end

  i = i + 1
end
scrollwindow = Gtk::ScrolledWindow.new.add @view
widget.add scrollwindow

end

end

class GenericList < Gtk::Object
attr_accessor :container
type_register
def initialize(opts={})
super()
@container = Gtk::HBox.new
@table = TestTable.new
get_data
@table.render_and_attach(@container)
end

def get_data
  i = 0

  50.times do
    @table.add_row(["asdf", "Na#{i}me", (i*5.2).to_s])
    i = i + 1
  end
end

end

window = Gtk::Window.new
list = GenericList.new
window << list.container
window.set_default_size 400, 400
window.show_all
Gtk.main

now it works. What the real problem was i don’t know, sorry. What have i
done?

  • First i removed the unnecessary subclassing of Float for EuroCurrency
  • Then i replaced all the self with @
  • removed the Glade stuff
  • setting all Column types to String
  • many smal changes

HTH detlef

  • First i removed the unnecessary subclassing of Float for EuroCurrency
  • setting all Column types to String

Setting all columns are String actually does the job. But a string can’t
efficiently sort numbers. (10… 104… 20 ) so my initial idea was to
subclass Float or Integer. This actually works.

What is causing problems is the self.fmt_string method inside my
subclass of Float/Integer etc.

By doing something like this
module Convert
def fmt_str(type,text)
if type == EuroCurrency
sprintf("%.2f",text.to_f).gsub(".",",")+" Euro"
end
end
module_function :fmt_str
end

class EuroCurrency < Float
end

and on the renderer

str_class = @column_types[i]
col.set_cell_data_func(renderer) do |col, renderer, model, iter|
renderer.text = Convert.fmt_str(str_class,renderer.text)
end

I don’t get that error. Strange…

After more weirdness about this error I “fixed” it

def connect_sort_update
unless @sort_update_handler == nil
@liststore.signal_handler_disconnect(@sort_update_handler)
end
@sort_update_handler =
@liststore.signal_connect(“sort-column-changed”){ |me|
col_id, ordering = me.sort_column_id
puts “sort column changed: #{col_id} #{ordering}”
connect_sort_update
}
end

On every signal call, it disconnects the signal and reconnects it. This
way it doesn’t seem to be collected by the GC.
Although this is very ugly, it solves my problem.

so you think that GC freed the signal handler procedure, and that caused
the GRClosure errors?

Yes, that seems to be the cause of the error. Search google for the
error message; we’ve discussed this before and there’s a patch in
launchpad that seems to fix it.

Dobai-Pataky Bálint wrote:

so you think that GC freed the signal handler procedure, and that caused
the GRClosure errors?

I think so, but I’m not sure what exactly happens there.
It seems that it never get collected when not emitted. When signal is
emitted (at least) once, it seems that it’s being freed up by the next
GC run.

Hi,

2008/3/2, Joachim G. [email protected]:

Detlef R. wrote:

Hi,

could you post a (at least partial) working example, please.

Ah, yes. I could finally track the problem down and make a demo. See
attached file. Try changing the sort bars several time, in this test I
need between 15 and 30 clicks.

I’ve fixed this problem in trunk.
Your test program should work well without any changes.

Thanks,

kou

Kouhei S. wrote:

I’ve fixed this problem in trunk.
Your test program should work well without any changes.

Yes, works!

Thank you!