[ruby-dev:3456] ioctl & thread (Re: [ruby-list:9173] Re: gtk)

From: "D.Kanda" <MAP2303@...>
Date: 1998-08-17 23:49:40 UTC
List: ruby-dev #3456
   かんだです。

>   とりあえず今夜せめて ioctl 部分を拡張モジュールに落としてきますので、そし
> たら流させて頂きます。ruby-dev の方がいいかな?

  ext化は手間どってしまって、まだです。
  が、とりあえず最小の再現ソースです。ioctl と thread を使うと駄目らしい。
  gtkは関係なかったです。
  環境は、linux(i586 pgcc & i686 gcc), ruby-1.1c2 です。

  ioctl部分が linux 依存なので、それ以外の機種だと変更がいると思います。



require 'thread'

class AudioCD
  # 環境によって違う可能性大。
  # <linux/cdrom.h> か <sundev/srreg.h> に書かれているらしい。
  #
  CDROMSUBCHNL	    = 0x0000530B #struct cdrom_subchnl *        // I-O
  CDROM_MSF = 0x02 # "minute-second-frame": binary, not bcd here!

  @cd_fd = nil;
  def initialize(dev = "/dev/cdrom")
    @cd_fd = File.open(dev, "r") #throw io error
    @stat_mutex = Mutex.new
  end
  public

  class Foo; end
  def Foo.subchnl(cd_fd) #なんかクラスメソッドにした方が落ちるな…
    arg = "\000" *16
    arg[0] = CDROM_MSF
      
# 思うに、ioctl と thread の相性が悪いのかな
    begin
      # /dev/nullとかに対して実行したいけど、ioctl はよく知らない。
      ret = cd_fd.ioctl(CDROMSUBCHNL, arg)

# これを入れたほうが落ちやすい。
# 入れなくても、結局はスレッドの変更が原因の一つになっている気がする。
      Thread.pass

    rescue Errno::EIO
      printf("%s at %s\n",  $!, $@)
    end
  end

  public
  def updateStatus()
    begin
      if @stat_mutex.try_lock
	Foo.subchnl(@cd_fd)
      else
	@stat_mutex.lock
      end
    ensure
      @stat_mutex.unlock
    end
  end


#test()
# ioctl に対して同期を取らない場合。
# 偶然かもしれないが、こっちだとさらに妙な現象がでるようだ。
#
#   Fenarinarsa:src/ruby-1.1c2 >ruby cd2.rb
#   ce2.rb:31: [BUG] Segmentation fault
#(ファイル名が変わるとは…^^;)
#   zsh: abort (core dumped)  ruby cd2.rb
#
# こんなのもあった。
#   Fenarinarsa:src/ruby-1.1c2 >ruby cd2.rb
#   cd2.rb:18:in `subchnl': undefined method `ioctl' for FALSE (NameError)
#	from cd2.rb:30:in `test'
#	from cd2.rb:59
# subchnl() の引数(=@cd_fd) が FALSE になっちゃてます。
# 変数名(id) -> メモリ位置のマッピングがずれるのかしら
#
  def test
    Foo.subchnl(@cd_fd)
  end

end

#---------------------------------------------------------------------------
#   main
#---------------------------------------------------------------------------
@cd = AudioCD.new
Thread.start {
  while true
    @cd.updateStatus
#    @cd.test()
#  sleep(0.1) #sleepしない方が妙なエラーが出やすい気がする。

# GCを入れると劇的に落ちる。入れるのはどこでもいいけど。回数の多いところに。
    GC.start
  end
}

while true
  @cd.updateStatus
#  @cd.test()
#  sleep(0.1) #上に同じ。
end

exit

In This Thread

Prev Next