qt4-ruby crash


M

Marco Polo

Hi,

i had one of the worst idea in my life one month ago: port a working
ruby-gtk2 app to ruby-qt4. Not only it becomes a non-sense to use ruby
since your code looks like to a c++ app written in another language (you
almost lose all advantages of a clean ruby port like ruby-gnome2,
exception messages are unclear when it's qt related) but it crashes in a
way that is incredible:

/usr/lib/ruby/site_ruby/1.8/Qt/qtruby4.rb:2680: [BUG] object allocation
during garbage collection phase
ruby 1.8.7 (2010-08-16 patchlevel 302) [x86_64-linux]

The first time i had this message, i surrounded a piece of code with
calls to GC.disable and GC.enable to make the damn thing work.

And now i fall in the same problem in another part of code but this
time, GC.enable/disable doesn't work.

It's related to qt::treewidget: it works if sorting is not enabled but
it crashes if it's enabled.

Does anyone have any idea about this problem?

Thanks.

Linux 2.6.35.6-48.fc14.x86_64, qt 4.7.1, kde 4.5.3
 
Ad

Advertisements

S

Stefano Crocco

Hi,

i had one of the worst idea in my life one month ago: port a working
ruby-gtk2 app to ruby-qt4. Not only it becomes a non-sense to use ruby
since your code looks like to a c++ app written in another language (you
almost lose all advantages of a clean ruby port like ruby-gnome2,
exception messages are unclear when it's qt related) but it crashes in a
way that is incredible:

/usr/lib/ruby/site_ruby/1.8/Qt/qtruby4.rb:2680: [BUG] object allocation
during garbage collection phase
ruby 1.8.7 (2010-08-16 patchlevel 302) [x86_64-linux]

The first time i had this message, i surrounded a piece of code with
calls to GC.disable and GC.enable to make the damn thing work.

And now i fall in the same problem in another part of code but this
time, GC.enable/disable doesn't work.

It's related to qt::treewidget: it works if sorting is not enabled but
it crashes if it's enabled.

Does anyone have any idea about this problem?

Thanks.

Linux 2.6.35.6-48.fc14.x86_64, qt 4.7.1, kde 4.5.3

Which version of qt-ruby are you using? I remember having some problems like
the one you're experiencing, but it was a long time ago.

Stefano
 
M

Marco Polo

This is my version, sorry for not giving it in my post!

QtRuby.x86_64 4.5.3-1.fc14

marco
 
S

Stefano Crocco

This is my version, sorry for not giving it in my post!

QtRuby.x86_64 4.5.3-1.fc14

marco

If I understand correctly, that's the version shipped with the latest stable
KDE, so it should be up to date. This is strange. Can you post the code
causing the crash? Also, you are most likely to obtain help asking on the qt-
ruby forum or mailing list. The former is at
http://rubyforge.org/forum/forum.php?forum_id=723 , while you can subscribe to
the mailing list at https://mail.kde.org/mailman/listinfo/kde-bindings (note
that this is a mailing list for all the KDE bindings, not just the ruby ones,
so be sure to mention you're using qt-ruby). I always found the developers
very helpful so I'm sure they'll try to help you. However, I think you'll need
to provide a C-level backtrace of the crash to sort out this issue.

Stefano
 
M

Marco Polo

This is the piece of code that makes ruby to crash:

<code>
def load_plists
#return
@ui.lists_tv.clear
DBIntf::connection.execute( "SELECT * FROM plists ORDER BY
LOWER(sname)" ) do |row|
@ui.lists_tv.addTopLevelItem(Qt::TreeWidgetItem.new {
setText(0, row[0]); setText(1, row[1]) })
end
end
</code>

I added the order by statement to get rid from the sort in the tree
view. The tree view comes from a qtdesigner ui file and is used as a
list
view, there are no children and only 16 entries in the sqlite3 plists
table.
In another similar case, slightly more complex, i have 2000+ entries and
it works even if sort is enabled but only if the code is surrounded with
GC.enable/disable:

<code>
def load_entries
clear

GC.disable
has_compile = false
DBIntf::connection.execute(generate_sql) do |row|
map_row_to_entry(row, Qt::TreeWidgetItem.new)
has_compile = true if row[ROW_REF] == "0"
end
unless @mc.main_filter.empty?
unless has_compile
map_row_to_entry(["0", "Compilation"],
Qt::TreeWidgetItem.new)
end
end

GC.enable
return self
end
</code>

In this case, the class inherits a treeview.

Thanks for the links and your help.

marco
 
S

Stefano Crocco

This is the piece of code that makes ruby to crash:

<code>
def load_plists
#return
@ui.lists_tv.clear
DBIntf::connection.execute( "SELECT * FROM plists ORDER BY
LOWER(sname)" ) do |row|
@ui.lists_tv.addTopLevelItem(Qt::TreeWidgetItem.new {
setText(0, row[0]); setText(1, row[1]) })
end
end
</code>

I added the order by statement to get rid from the sort in the tree
view. The tree view comes from a qtdesigner ui file and is used as a
list
view, there are no children and only 16 entries in the sqlite3 plists
table.
In another similar case, slightly more complex, i have 2000+ entries and
it works even if sort is enabled but only if the code is surrounded with
GC.enable/disable:

<code>
def load_entries
clear

GC.disable
has_compile = false
DBIntf::connection.execute(generate_sql) do |row|
map_row_to_entry(row, Qt::TreeWidgetItem.new)
has_compile = true if row[ROW_REF] == "0"
end
unless @mc.main_filter.empty?
unless has_compile
map_row_to_entry(["0", "Compilation"],
Qt::TreeWidgetItem.new)
end
end

GC.enable
return self
end
</code>

In this case, the class inherits a treeview.

Thanks for the links and your help.

marco

First of all, just to be clear, you're using tree widgets, not tree views.
Asides from this, I don't see anything wrong with your code. As I said in my
other mail, I think your best option is to post the C backtrace from the crash
to either the qt-ruby forum or mailing list. If you do, you may be asked for a
small program which reproduces the crash. I guess this might not be easy to
do.

If all else fails, you can try replacing the tree widget with a tree view
coupled with a Qt::StandardItemModel. Model/View-based widgets (Qt::ListView,
Qt::TreeView and Qt::TableView) are more flexible than their *Widget
counterparts and, when used with a Qt::StandardItemModel, are just as easy to
use.

If you choose to do so, you can create the view widget using the designer just
like you did with the tree widget. Then, in your widget's constructor do
something like (referring to your first piece of code):

@ui.lists_tv.model = Qt::StandardItemModel.new @ui.lists_tv

Then, in your load_plists method, you can do something like this:

@ui.lists_tv.clear
DBIntf::connection.execute( "SELECT * FROM plists ORDER BY LOWER(sname)" ) do
|row|
items = row.map{|i| Qt::StandardItem.new i}
@ui.lists_tv.model.append_row items
end

Even if you don't find TreeView better than TreeWidget, it may avoid the
crashes you see.


By the way, referring to your first message, why do you think that using qt-
ruby "our code looks like to a c++ app written in another language (you
almost lose all advantages of a clean ruby port like ruby-gnome2, exception
messages are unclear when it's qt related)"? (I never used ruby-gnome2, so I
can't compare with it).

Looking at your code, it seems you aren't aware that you can replace camel-
case names with snake-case ones (for example, addTopLevelItem could have been
written as add_top_level_item). Also, in case you aren't aware, methods
starting with is are availlable in the more rubysh form ending with a question
mark: isEmpty can also be called as empty?. I'm not sure if this is also the
case for methods starting with has. Setters methods taking a single argument
are also availlable as methods ending with =. For instance, the Qt::TreeView
setColumnCount method can also be written as column_count =.

Regarding the exception issue, I'm afraid I have to agree they are often
wrong. In particular (I guess this is what you're referring to), qt-ruby
raises NoMethodError even when the method does exist, but takes different
arguments from what you passed. I read somewhere that this is to mimic the
behaviour you get in C++, where using the wrong arguments would make the
compiler complain about calling a non existing method. I thought to post a bug
report about this but decided against that knowing they would have rejected it
because of compatibility issues.

I hope this helps

Stefano
 
Ad

Advertisements

M

Marco Polo

Thanks for your help, I had in mind to use a custom model for the tree
view. I was speaking of tree view because it's a generic name for any
kind of hierarchical view even if it's implemented as a treewidget.

I decided not to use the camel case just because it makes clear what
comes from qt and what comes from my own code, especially in classes
that inherit from a qt object. And I'm not sure that using camel case
for methods that you override in subclasses works... I had some bad
surprises but these are my first steps in the qt world so I may have
done something wrong.

I'm also relatively new in ruby, I gave it a try a year ago and fell in
love with it. I'm playing with it at home, being a full time c++, perl
developer on various unix boxes, and managed to get full running app in
less than a year with gtk2. But being upset with some gtk2 limitations
(you don't have multiple selection in tree views, for example), I
decided to try qt.

May be I should have started with a smaller project to start with qt
but as I exactly knew what I had to try, I wanted to check the pitfalls
I fell in with gtk as soon as possible.

And what I wanted to say when I said it was looking like c++ is that the
ruby-gnome2 port of gtk2 is done in a rubysh style (but appears to be
incomplete). Qt looks very interesting when you do c++ but having to use
a class like QVariant in ruby is, in my opinion, the exact anti-rubysh
way!

Anyway, I will try the treeviews in the way you said and may be will you
soon have news from me!

And thanks again for your help and your time!

marco
 
Ad

Advertisements

M

Marco Polo

It works! I changed one of my treewidget to a treeview and it works even
if the calls to GC.enable/disable are removed. I hope this solution will
work for all my tree views (a lot!).

Thanks again.

marco
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top