ひだかです。

VisualuRuby で小さなプログラムを書いていて見つけたのですが、
以下のプログラムが cygwin 版だと動いて、mingw32 / mswin32 版だと、
開始ボタンを押すと

  アプリケーションエラー
  例外 unknown software exception (0xc0000029)が 
  アプリケーションの0x77fb16cc で発生しました

と言って動きません。環境は Windows2000SP2で、

mswin32版はうささんのところから持ってきた 
   ruby 1.6.5 (2001-09-19) [i586-mswin32]
cygwin版はわたなべひろふみさんのところから持ってきた
   ruby 1.6.5 (2001-09-19) [i386-cygwin]
mingw32版はデバッガにかけてみようと思って自分で 1.6-snapshot を
cygwin の Mingw 環境で make したもの、
   ruby 1.6.5 (2001-10-05) [i386-mingw32]

です。バージョン揃えろよって感じですが何も考えていなかったので
すみません。

-----------------------------------------------------------------
#!/usr/local/bin/ruby -KS

require 'win32ole'
require 'vr/vruby'
require 'vr/vrcontrol'
require 'vr/vrlayout'

class VRTestForm < VRForm
  include VRStdControlContainer
  include VRHorizLayoutManager

  def construct
    self.caption = 'WebTester'
    addControl(VRButton, "btnView", "", 0)
    addControl(VRButton, "btnStart", "開始", 0)
    self.move 0, 0, 100, 80
    @count = 0
  end

  def btnStart_clicked
    Thread.start {
      1.upto(3000) do | i |
        @btnView.caption = "#{i}"
        Thread.pass                 # ←これがあるとmswin32版では落ちる
      end
      @count += 1
      @btnStart.caption = @count
    }
  end
end

# form 作成
frm = VRLocalScreen.showForm VRTestForm

# Windows MessageLoop
# VRLocalScreen.addIdleproc Proc.new{ Thread.pass }  
VRLocalScreen.messageloop
-----------------------------------------------------------------
で、とりあえず mingw32 版で gdb で調べてみたところ、
eval.c の stack_extend あたりで落ちてしまいます。

メッセージハンドラでスレッドを作って、かつ、そのスレッド内部で
Thread.pass するとダメなようで、スレッド内部の Thread.pass を削除して、
addIdleproc の行を有効にすれば問題なくなってしまいますし、

ちょっとプログラムの意味としては変わってしまうのですが、以下のように
messageloop の前に Thread を作って stop しておいて、それを run する分には
Thread.pass しても問題ありません。
-----------------------------------------------------------------
#!/usr/local/bin/ruby -KS

#require 'win32ole'
require 'vr/vruby'
require 'vr/vrcontrol'
require 'vr/vrlayout'

class VRTestForm < VRForm
#  include VRClosingSensitive
  include VRStdControlContainer
  include VRHorizLayoutManager

  def construct
    self.caption = 'WebTester'
    addControl(VRButton, "btnView", "", 0)
    addControl(VRButton, "btnStart", "開始", 0)
    self.move 0, 0, 100, 80
    @count = 0
  end

  def btnStart_clicked
    @th.run
  end

  def makeThread
    @th = Thread.start {
      while(true) do
        Thread.stop
        1.upto(30) do | i |
          @btnView.caption = "#{i}"
          Thread.pass
        end
        @count += 1
        @btnStart.caption = @count
      end
    }
  end
end

# form 作成
frm = VRLocalScreen.showForm VRTestForm

frm.makeThread

# Windows MessageLoop
# VRLocalScreen.addIdleproc Proc.new{ Thread.pass }  
VRLocalScreen.messageloop
-----------------------------------------------------------------

ちなみにこれと同様のプログラムを、FXRuby で作ると同様に
cygwinは平気でmswin32だと落ちてしまいます。

# Ruby/Tk だとmswin32でも平気のようです。
# 全然仕組みが違うみたいだからあたりまえなのかな?

さて。ぼくはWin32内部のこともRubyのthreadのしくみとかもよく
わかっていなくて、何を調べたらいいのかまだ見当もつかないのですが、
どなたかヒントでも教えて頂けないでしょうか。

-- 
ひだかたかひろ  cv8t-hdk / asahi-net.or.jp
   逆引きFXRubyやってます。http://takahr.dhis.portside.net/cgi-
bin/rwiki.cgi
   ちょっと疲れてきたので協力者募集中。