From ruby-ext-admin@netlab.co.jp Fri Dec 8 16:59:06 2000 Received: from voscc.nagaokaut.ac.jp (voscc.nagaokaut.ac.jp [133.44.1.100]) by blade.nagaokaut.ac.jp (8.8.8/8.8.8/Debian/GNU) with ESMTP id QAA00977; Fri, 8 Dec 2000 16:59:06 +0900 Received: from helium.ruby-lang.org (helium.ruby-lang.org [210.251.121.214]) by voscc.nagaokaut.ac.jp (8.9.3/3.7W) id QAA38213; Fri, 8 Dec 2000 16:54:32 +0900 (JST) Received: from helium.ruby-lang.org (localhost [127.0.0.1]) by helium.ruby-lang.org (Postfix) with ESMTP id 9EE8D30AE; Fri, 8 Dec 2000 16:53:28 +0900 (JST) Date: Fri, 8 Dec 2000 16:53:15 +0900 (JST) From: Jun Adachi Reply-To: ruby-ext@netlab.co.jp Subject: [ruby-ext:01445] Unexpected Error Exit when using Ruby/Gtk To: ruby-ext@netlab.co.jp (ruby-ext ML) Message-Id: <200012080753.QAA15534@tdonaldot.lab.okidata.co.jp> X-ML-Name: ruby-ext X-Mail-Count: 01445 X-MLServer: fml [fml 3.0pl#17]; post only (only members can post) X-ML-Info: If you have a question, send e-mail with the body "help" (without quotes) to the address ruby-ext-ctl@netlab.co.jp; help= Precedence: bulk Lines: 99 安達@沖データです。 すみません。おそらくRuby/Gtkのバグではなくて、Gtk/Gdk/Glibの不具合の可 能性が高いと思うのですが、最後まで追えていないのでとりあえず報告してお きます。 <不具合の状況> ruby 1.6.1 (2000-09-27) [i386-freebsdelf3.4](Ruby/Gtk-0.23, Gtk1.2.8) において、Ruby/Gtkを用いたプログラムAと、それを呼び出す親プログラムBに おいて、期待したexitステータスが得られない場合がある。ruby 1.6.0 (2000-09-19)[i686-linux](Ruby/Gtk-0.23, Gtk1.2.8)でも発生を確認した。 <不具合の発生条件> 親プログラムBが、プログラムAを呼び出す前に$stdin, $stdout, $stderrのい ずれかをcloseしていること。 <不具合の確認> 最後に添付するプログラム実行する。Helloボタンを押すとtrue、Worldボタン を押すとfalseの表示が期待される動作なのだが、実際にはどちらでもfalseと なる。 <不具合の回避> $stdin, $stdout, $stderrをクローズしなければ回避できる。 <不具合の追跡状況> FreeBSD付属のktraceでプログラムAのシステムコールの呼び出しを追跡した結 果、次のことが判明した。 プログラムBにおいてfdの0, 1, 2のうちどれかが閉じてあると、Xサーバとの 通信にその閉じたfdが利用される。ところが、終了ステータス表示(p "delete: #{$state}")の後、つまりexit(又はatexit)処理の中でfdの0, 1, 2 を無条件に閉じている。そのため、gdkが登録したatexit処理の一部である XCloseDisplayがエラーとなる。結果として、Rubyスクリプトの指示した終了 ステータスに関係なくエラーが帰る。 <不具合に関する予測> fd0, 1, 2を閉じている主体が、gtk/gdk/glib/システムのいずれかまでは、調 査しなかった。しかし、システムはatexit関数群を呼んだ後にストリームを閉 じることになっているので、gtk/gdk/glibの登録している処理がこのような状 況を予想しておらず、内部で不整合をおこしていると思われる。 --helloworld.rb: プログラムA #!/usr/local/bin/ruby require 'gtk' def destroy(widget) p "destroy: #{$state}" exit($state) end def main $state = 0 window = Gtk::Window::new window.signal_connect("destroy") { |*args| destroy(*args) } window.border_width = 10 hbox = Gtk::HBox.new.show button = Gtk::Button::new("Hello") button.signal_connect("clicked") {|*args| $state = 0 print "Hello\n" window.destroy } hbox.add(button) button.show() button = Gtk::Button::new("World") button.signal_connect("clicked") {|*args| $state = 1 print "World\n" window.destroy } hbox.add(button) button.show() window.add(hbox) window.show() Gtk::main() end main --testmain.rb: プログラムA #!/usr/bin/env ruby $stderr.close bool = system("./helloworld.rb") p bool -- *------* adachi@okidata.co.jp |人∧鷲| 沖データ ソフトウェア開発部 | <女> | 安達 淳 |牛∨獅| *------*