[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