From: Kouhei S. <ko...@co...> - 2014-03-08 15:09:33
|
須藤です。 In <531...@gm...> "[ruby-gnome2-devel-ja] Gio2がSEGVする件について" on Sat, 08 Mar 2014 22:21:56 +0900, hiroshi hatake <cos...@gm...> wrote: > Gio2が`bundle exec rake`するとSEGVするようになってしまいました。。 > > 今までは問題がなく動いていたのですが、原因がわからないです。 > Issueには登録したのですが、こちらの環境のせいもあるかも知れません。 > (Travis CIでは落ちてないですし…) > > Ruby-GNOME2のプロジェクトルートで > bundle exec rakeした実行結果のログを添付して送ります。 > (かなりデカいです。) ありがとうございます! ログがあってとても助かりました! たぶん、 https://github.com/ruby-gnome2/ruby-gnome2/commit/d3a9726f0406cb5401ac9f9fd3e3cd7991834efe で治っていると思います。 参考までに直し方を説明します。 Failure: Exception raised: RangeError(<integer 140026789758480 too big to convert to `unsigned int'>) test_buffered_input_stream(TestBufferedInputStream) /media/Data2/Gitrepo/ruby-gnome2/gio2/test/test-buffered-input-stream.rb:19:in `test_buffered_input_stream' 16: 17: class TestBufferedInputStream < Test::Unit::TestCase 18: def test_buffered_input_stream => 19: assert_nothing_raised do 20: Gio::BufferedInputStream.new(Gio::FileInputStream.new) 21: end 22: end ↑から、RubyからCの数値型への変換に問題があることがわかりま す。32bit以上の数値を表しているRubyのオブジェクトをCの unsigned intへ変換するときにでるやつです。RubyのCのAPIでいう とNUM2UINTしているところです。NUM2UINTをNUM2ULONGにしてやれ ばよいパターンです。 で、どこでNUM2UINTしてしまっているのかはこのログからはわかり ません。 他のエラーを眺めているとこんなのがあります。 2014-03-08 21:56:54 +0900 running test for /media/Data2/Gitrepo/ruby-gnome2/clutter -------------------------------------------------------------------------------- /media/Data2/Gitrepo/ruby-gnome2/gobject-introspection/lib/gobject-introspection/loader.rb:161:in `define_error': integer 140067343098880 too big to convert to `unsigned int' (RangeError) from /media/Data2/Gitrepo/ruby-gnome2/gobject-introspection/lib/gobject-introspection/loader.rb:161:in `define_error' ... giのloader.rbの中でdefine_errorしているときに同じエラーが起 きていることがわかります。ということで、このメソッドの定義を 眺めます。 https://github.com/ruby-gnome2/ruby-gnome2/blob/master/gobject-introspection/ext/gobject-introspection/rb-gi-loader.c#L91 NUM2UINTしているのは二箇所あって、Rubyの数値をGQuarkの変換す るのと、GTypeに変換するために使っています。どっちかまたは両 方が怪しいです。 GLibのヘッダーファイルをgrepしてみます。 % grep -r typedef /usr/include/glib-2.0/ | grep ' GQuark;' /usr/include/glib-2.0/glib/gquark.h:typedef guint32 GQuark; GQuarkはいつも32bitだということがわかります。 % grep -r typedef /usr/include/glib-2.0/ | grep ' GType;' /usr/include/glib-2.0/gobject/glib-types.h:typedef gsize GType; /usr/include/glib-2.0/gobject/gtype.h:typedef gsize GType; /usr/include/glib-2.0/gobject/gtype.h:typedef gulong GType; GTypeは64bitになりそうです。ということで、GTypeの方が問題な 気がします。 ということで、前述のパッチになります。 あと、 /media/Data2/Gitrepo/ruby-gnome2/gio2/lib/gio2/loader.rb:68: warning: previous definition of ContentType was here みたいなのがモリモリでているのも別の問題としてあります。これ は、2回GObject Introspectionのロードが走っているからです。ロー ド中に↑のエラーでロードが途中で終わってしまっているため、再 度ロードしようとしてしまっています。 これは、GObject Introspectionのロードを必要になるときまで遅 延しているからで、もう少しだけ詳しい説明がここにあります。 http://magazine.rubyist.net/?0043-BeALibraryDeveloper#l14 コードで言えばここらへんです。 https://github.com/ruby-gnome2/ruby-gnome2/blob/master/gio2/lib/gio2.rb#L47-54 def init loader = Loader.new(self) loader.load("Gio") class << self remove_method(:init) remove_method(:const_missing) end end ロードに成功したときだけremove_methodしているのが悪くて、 initの先頭でremove_methodしてしまえば、ロードの途中でエラー が発生しても再度ロードすることはなくなります。 なので、こんな風に直してもらえないでしょうか!? def init class << self remove_method(:init) remove_method(:const_missing) end loader = Loader.new(self) loader.load("Gio") end 似たようなコードがclutter/lib/clutter.rbとか Ruby/GObjectIntrospection使ったやつ全部にあるはずです。。。 |