Trouble with callback causing segmentation faults

68 views
Skip to first unread message

Dominic Muller

unread,
Jul 28, 2014, 5:25:48 AM7/28/14
to ruby...@googlegroups.com
I've spent the last couple days trying to figure out if I'm doing anything wrong, and I've checked over my code a dozen times, but cannot figure out what's causing this issue.

Here is a shortened version of the code which is guaranteed to generate the seg fault.  I apologize for the size, but these structs are required to make a call to waveOutOpen:

require 'ffi'

class HWAVEOUT < FFI::Struct
  layout :i, :int
end

class WAVEFORMATEX < FFI::Struct
  def initialize
    self[:wFormatTag] = 1
    self[:nChannels] = 1
    self[:nSamplesPerSec] = 44100
    self[:wBitsPerSample] = 16
    self[:cbSize] = 0
    self[:nBlockAlign] = (self[:wBitsPerSample] >> 3) * self[:nChannels]
    self[:nAvgBytesPerSec] = self[:nBlockAlign] * self[:nSamplesPerSec]
  end
  layout(
    :wFormatTag, :ushort,
    :nChannels, :ushort,
    :nSamplesPerSec, :ulong,
    :nAvgBytesPerSec, :ulong,
    :nBlockAlign, :ushort,
    :wBitsPerSample, :ushort,
    :cbSize, :ushort
  )
end

class WAVEHDR < FFI::Struct     
  layout(
    :lpData, :pointer,
    :dwBufferLength, :ulong,
    :dwBytesRecorded, :ulong,
    :dwUser, :ulong,
    :dwFlags, :ulong,
    :dwLoops, :ulong,
    :lpNext, :pointer,
    :reserved, :ulong
  )
end

class Sound
  extend FFI::Library

  ffi_lib :winmm
 
  callback :waveOutProc, [:pointer, :uint, :ulong, :ulong, :ulong], :void
  attach_function :waveOutOpenCallback, :waveOutOpen, [:pointer, :uint, :pointer, :waveOutProc, :ulong, :ulong], :uint
  attach_function :waveOutOpenNull, :waveOutOpen, [:pointer, :uint, :pointer, :ulong, :ulong, :ulong], :uint
 
  WaveOutProc = Proc.new do |hwo, mMsg, dwCallback, dwParam1, dwParam2|
    puts mMsg
    return
  end
 
end

hWaveOut = HWAVEOUT.new
wfx = WAVEFORMATEX.new

puts "waveOutOpen returns 0 (no error) if I don't use the callback form"
puts Sound.waveOutOpenNull(hWaveOut.pointer, -1, wfx.pointer,0,0,0)

puts "but if I use a callback, the moment it returns from the callback, there is a seg fault"
puts "note that the code inside the callback runs, as I am puts-ing the mMsg which is 955"
puts "for WOM_OPEN which tells us the device was opened."
puts "this is on ruby 1.9.3p484 (2013-11-22) [i386-mingw32] running 1.9.3 x86-mingw32 on"
puts "Windows 7"
puts Sound.waveOutOpenCallback(hWaveOut.pointer, -1, wfx.pointer,Sound::WaveOutProc,0,0x30000)

If you'd like it, here is the output of this code to my console:

waveOutOpen returns 0 (no error) if I don't use the callback form
0
but if I use a callback, the moment it returns from the callback, there is a seg fault
note that the code inside the callback runs, as I am puts-ing the mMsg which is 955
for WOM_OPEN which tells us the device was opened.
this is on ruby 1.9.3p484 (2013-11-22) [i386-mingw32] running 1.9.3 x86-mingw32 on
Windows 7
955
sound.rb:67: [BUG] Segmentation fault
ruby 1.9.3p484 (2013-11-22) [i386-mingw32]

-- Control frame information -----------------------------------------------
c:0004 p:---- s:0018 b:0018 l:000017 d:000017 CFUNC  :waveOutOpenCallback
c:0003 p:0282 s:0009 b:0008 l:001144 d:0023d4 EVAL   sound.rb:67
c:0002 p:---- s:0004 b:0004 l:000003 d:000003 FINISH
c:0001 p:0000 s:0002 b:0002 l:001144 d:001144 TOP

-- Ruby level backtrace information ----------------------------------------
sound.rb:67:in `<main>'
sound.rb:67:in `waveOutOpenCallback'

-- C level backtrace information -------------------------------------------
C:\Windows\SysWOW64\ntdll.dll(ZwWaitForSingleObject+0x15) [0x7721f8d1]
C:\Windows\syswow64\kernel32.dll(WaitForSingleObjectEx+0x43) [0x754f1194]
C:\Windows\syswow64\kernel32.dll(WaitForSingleObject+0x12) [0x754f1148]
C:\Ruby193\bin\msvcrt-ruby191.dll(rb_vm_bugreport+0xf9) [0x62e5cf51]
C:\Ruby193\bin\msvcrt-ruby191.dll(rb_name_err_mesg_new+0x17a) [0x62d3a862]
C:\Ruby193\bin\msvcrt-ruby191.dll(rb_bug+0x2f) [0x62d3b53f]
C:\Ruby193\bin\msvcrt-ruby191.dll(rb_check_safe_str+0x194) [0x62def0bc]
 [0x004011e6]
C:\Windows\syswow64\kernel32.dll(GetProfileStringW+0x12d67) [0x75530303]
C:\Windows\SysWOW64\ntdll.dll(RtlKnownExceptionFilter+0xb7) [0x772774ff]

-- Other runtime information -----------------------------------------------

* Loaded script: sound.rb

* Loaded features:

    0 enumerator.so
    1 C:/Ruby193/lib/ruby/1.9.1/i386-mingw32/enc/encdb.so
    2 C:/Ruby193/lib/ruby/1.9.1/i386-mingw32/enc/iso_8859_1.so
    3 C:/Ruby193/lib/ruby/1.9.1/i386-mingw32/enc/trans/transdb.so
    4 C:/Ruby193/lib/ruby/1.9.1/i386-mingw32/rbconfig.rb
    5 C:/Ruby193/lib/ruby/site_ruby/1.9.1/rubygems/compatibility.rb
    6 C:/Ruby193/lib/ruby/site_ruby/1.9.1/rubygems/defaults.rb
    7 C:/Ruby193/lib/ruby/site_ruby/1.9.1/rubygems/deprecate.rb
    8 C:/Ruby193/lib/ruby/site_ruby/1.9.1/rubygems/errors.rb
    9 C:/Ruby193/lib/ruby/site_ruby/1.9.1/rubygems/version.rb
   10 C:/Ruby193/lib/ruby/site_ruby/1.9.1/rubygems/requirement.rb
   11 C:/Ruby193/lib/ruby/site_ruby/1.9.1/rubygems/platform.rb
   12 C:/Ruby193/lib/ruby/site_ruby/1.9.1/rubygems/basic_specification.rb
   13 C:/Ruby193/lib/ruby/site_ruby/1.9.1/rubygems/stub_specification.rb
   14 C:/Ruby193/lib/ruby/site_ruby/1.9.1/rubygems/util/stringio.rb
   15 C:/Ruby193/lib/ruby/site_ruby/1.9.1/rubygems/specification.rb
   16 C:/Ruby193/lib/ruby/site_ruby/1.9.1/rubygems/exceptions.rb
   17 C:/Ruby193/lib/ruby/site_ruby/1.9.1/rubygems/defaults/operating_system.rb
   18 C:/Ruby193/lib/ruby/site_ruby/1.9.1/rubygems/core_ext/kernel_gem.rb
   19 C:/Ruby193/lib/ruby/1.9.1/thread.rb
   20 C:/Ruby193/lib/ruby/1.9.1/monitor.rb
   21 C:/Ruby193/lib/ruby/site_ruby/1.9.1/rubygems/core_ext/kernel_require.rb
   22 C:/Ruby193/lib/ruby/site_ruby/1.9.1/rubygems.rb
   23 C:/Ruby193/lib/ruby/site_ruby/1.9.1/rubygems/path_support.rb
   24 C:/Ruby193/lib/ruby/1.9.1/i386-mingw32/enc/utf_16le.so
   25 C:/Ruby193/lib/ruby/1.9.1/i386-mingw32/enc/trans/utf_16_32.so
   26 C:/Ruby193/lib/ruby/1.9.1/i386-mingw32/enc/trans/single_byte.so
   27 C:/Ruby193/lib/ruby/site_ruby/1.9.1/rubygems/dependency.rb
   28 C:/Ruby193/lib/ruby/gems/1.9.1/gems/ffi-1.9.3-x86-mingw32/lib/1.9/ffi_c.so
   29 C:/Ruby193/lib/ruby/gems/1.9.1/gems/ffi-1.9.3-x86-mingw32/lib/ffi/platform.rb
   30 C:/Ruby193/lib/ruby/gems/1.9.1/gems/ffi-1.9.3-x86-mingw32/lib/ffi/types.rb
   31 C:/Ruby193/lib/ruby/gems/1.9.1/gems/ffi-1.9.3-x86-mingw32/lib/ffi/library.rb
   32 C:/Ruby193/lib/ruby/gems/1.9.1/gems/ffi-1.9.3-x86-mingw32/lib/ffi/errno.rb
   33 C:/Ruby193/lib/ruby/gems/1.9.1/gems/ffi-1.9.3-x86-mingw32/lib/ffi/pointer.rb
   34 C:/Ruby193/lib/ruby/gems/1.9.1/gems/ffi-1.9.3-x86-mingw32/lib/ffi/memorypointer.rb
   35 C:/Ruby193/lib/ruby/gems/1.9.1/gems/ffi-1.9.3-x86-mingw32/lib/ffi/struct_layout_builder.rb
   36 C:/Ruby193/lib/ruby/gems/1.9.1/gems/ffi-1.9.3-x86-mingw32/lib/ffi/struct.rb
   37 C:/Ruby193/lib/ruby/gems/1.9.1/gems/ffi-1.9.3-x86-mingw32/lib/ffi/union.rb
   38 C:/Ruby193/lib/ruby/gems/1.9.1/gems/ffi-1.9.3-x86-mingw32/lib/ffi/managedstruct.rb
   39 C:/Ruby193/lib/ruby/gems/1.9.1/gems/ffi-1.9.3-x86-mingw32/lib/ffi/callback.rb
   40 C:/Ruby193/lib/ruby/gems/1.9.1/gems/ffi-1.9.3-x86-mingw32/lib/ffi/io.rb
   41 C:/Ruby193/lib/ruby/gems/1.9.1/gems/ffi-1.9.3-x86-mingw32/lib/ffi/autopointer.rb
   42 C:/Ruby193/lib/ruby/gems/1.9.1/gems/ffi-1.9.3-x86-mingw32/lib/ffi/variadic.rb
   43 C:/Ruby193/lib/ruby/gems/1.9.1/gems/ffi-1.9.3-x86-mingw32/lib/ffi/enum.rb
   44 C:/Ruby193/lib/ruby/gems/1.9.1/gems/ffi-1.9.3-x86-mingw32/lib/ffi/version.rb
   45 C:/Ruby193/lib/ruby/gems/1.9.1/gems/ffi-1.9.3-x86-mingw32/lib/ffi/ffi.rb
   46 C:/Ruby193/lib/ruby/gems/1.9.1/gems/ffi-1.9.3-x86-mingw32/lib/ffi.rb

[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


This application has requested the Runtime to terminate it in an unusual way.
Please contact the application's support team for more information.

Further evidence that this isn't my fault is that another library using the midiout functions results in the same segmentation fault behavior when using the midioutproc callback.

Any help or insight would be appreciated.  If it helps, here are a couple links to the documentation for these functions:

http://msdn.microsoft.com/en-us/library/windows/desktop/dd743869%28v=vs.85%29.aspx
http://msdn.microsoft.com/en-us/library/windows/desktop/dd743866%28v=vs.85%29.aspx

Thanks,

- Dominic

Daniel Berger

unread,
Jul 29, 2014, 9:26:36 AM7/29/14
to ruby...@googlegroups.com
I don't think you want an explicit return in the callback.

Using 64-bit mingw it works ok once I remove the return from the callback function. Otherwise I get a LocalJump error.

However, I still get a segfault using 32-bit mingw or VC++ even with the return removed. Perhaps that's a clue?

Dan
Reply all
Reply to author
Forward
0 new messages