From: hiroshi h. <cos...@gm...> - 2014-03-08 15:32:47
|
畑ケです。 >> Gio2が`bundle exec rake`するとSEGVするようになってしまいました。。 >> >> 今までは問題がなく動いていたのですが、原因がわからないです。 >> Issueには登録したのですが、こちらの環境のせいもあるかも知れません。 >> (Travis CIでは落ちてないですし…) >> >> Ruby-GNOME2のプロジェクトルートで >> bundle exec rakeした実行結果のログを添付して送ります。 >> (かなりデカいです。) > ありがとうございます! > ログがあってとても助かりました! > > たぶん、 > https://github.com/ruby-gnome2/ruby-gnome2/commit/d3a9726f0406cb5401ac9f9fd3e3cd7991834efe > で治っていると思います。 治っているのを確認しました。 ついでにIssueもクローズしました! Travis CIでは落ちてないのでなんでだろうと悩んでいました。 32bit <-> 64bitの違いでハマりますねぇ。 > 参考までに直し方を説明します。 > > 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の方が問題な > 気がします。 > > ということで、前述のパッチになります。 なるほど…。解説ありがとうございます。 どこかで型の変換でエラーなっている、 までは見えましたけれどここまで追えていなかったです。 なのでIssueにしてみました。 > あと、 > > /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使ったやつ全部にあるはずです。。。 おっ、了解です。 斜めにザッと読む限り何箇所か発見しました。 見つけ次第直してコミットします! # ものすごい量のログになってしまっていたのは複数の要因があったんですね。。 |