シグナルハンドラが呼ぶvfprintfとかfprintf。

AIXでのバグをいくつかあげてくれたPerryさんから私信があって、情報を送ってくれたりしていたのですが、そのなかで[ruby-core:29497]の話がありました。
たとえばテストの中にある

% cat fail.rb
begin
  10000.times { Thread.new(true) {|x| x == false } }
rescue NoMemoryError, StandardError
end
p :ok

ですが、たまにとまってしまいます。これだけ実行すると
% ruby fail.rb
fail.rb:2: [BUG]
こんな感じで止まります。デバッガでアタッチすると、

ptrgl.$PTRGL() at 0xd0344750
malloc_y.malloc_y(0xc, 0x0, 0x20035870, 0x0, 0x0, 0x6c740049, 0x6d, 0x101f7550) at 0xd03c5b80
malloc_common.malloc_common_80_63(??) at 0xd0351634
_cleanup_push_72_6(??, ??, ??, ??) at 0xd01177b4
fwrite.fwrite_5_4(??, ??, ??, ??) at 0xd035ba94
doprnt._doprnt(??, ??, ??) at 0xd0353774
printf.vfprintf(??, ??, ??) at 0xd0352fc4
report_bug(file = (nil), line = 0, fmt = (nil), args = (nil)), line 225 in "error.c"
rb_bug(fmt = "Segmentation fault", ... = 0x200028b8, 0x2e022a20, 0x100000, 0x633333, 0xd032, 0x20456000, 0x3002f0b0), li
ne 245 in "error.c"
sigsegv(sig = 0, info = (nil), ctx = (nil)), line 617 in "signal.c"

で、ためしに配列を自動変数で取っておいて、vsnprintfしてfputsすると進むことがわかりました。malloc()しなそうな気がしただけです。
この先にもあるいくつかの関数でfprintfをsnprintf&fputsに摩り替えたりしていくと、ハングするまで出るものが増えます。

% ruby fail.rb
fail.rb:2: [BUG] Segmentation fault
ruby 1.9.2dev (2010-04-13 trunk 27329) [powerpc-aix5.3.0.0]

-- control frame ----------
c:0007 p:---- s:0017 b:0017 l:000016 d:000016 CFUNC  :new
c:0006 p:0017 s:0013 b:0013 l:001e3c d:000012 BLOCK  fail.rb:2
c:0005 p:---- s:0011 b:0011 l:000010 d:000010 FINISH
c:0004 p:---- s:0009 b:0009 l:000008 d:000008 CFUNC  :times
c:0003 p:0012 s:0006 b:0006 l:001e3c d:001d7c EVAL   fail.rb:2
c:0002 p:---- s:0004 b:0004 l:000003 d:000003 FINISH
c:0001 p:0000 s:0002 b:0002 l:001e3c d:001e3c TOP
---------------------------
-- Ruby level backtrace information ----------------------------------------
fail.rb:2:in `<main>'
fail.rb:2:in `times'
fail.rb:2:in `block in <main>'
fail.rb:2:in `new'

[NOTE]
You may have encountered a bug in the Ruby interpreter or extension libraries.
Bug reports are welcome.
For details: http://www.ruby-lang.org/bugreport.html

が、しかし!ここでまだハング。

ptrgl._ptrgl() at 0xd0344750
malloc_y.malloc_y(0xc, 0x0, 0x20035c30, 0x0, 0x0, 0x101b2051, 0x0, 0x0) at 0xd03c5b80
malloc_common.malloc_common_80_63(??) at 0xd0351634
_cleanup_push_72_6(??, ??, ??, ??) at 0xd01177b4
flsbuf._cleanup() at 0xd035c6f8
abort.abort() at 0xd03c8b2c
rb_bug(fmt = "Segmentation fault", ... = 0x20002c70, 0x2e022a20, 0x100000, 0x633333, 0xd032, 0x2b2bb400, 0x3002f0b0), line 261 in "error.c"
sigsegv(sig = 0, info = (nil), ctx = (nil)), line 617 in "signal.c"

abort()のなかでもやっちまっているみたいで、手の施しようがありません。
たとえばこことかみると、abort()は非同期シグナルセーフなはずなんですが。AIXではSIGSEGVのハンドラを入れないぐらいしか思いつきません。ほかのOSでハングしないかと思ってとりあえずnetbsdを入れたりしています。