[Haskell-cafe] Problems using Storable.poke* from separate OS thread.

Corey O'Connor coreyoconnor at gmail.com
Sun Jan 21 15:24:24 EST 2007


The short version: If a haskell routine exported to C is called from a
CoreAudio IO Proc, which is on a separate thread than the main thread, the
Haskell routine seams to exit early without notice.  If the same routine is
called from the main thread the routine produces correct output. Any ideas
on why Storeable.poke* would cause problems in this situation?

The long version:
I'm attempting to generate audio using Haskell and CoreAudio.* For a start I
tried converting Noel Cragg's HAL sinewave demo to process the audio frames
in Haskell. The original is here:
http://www.red-bean.com/~noel/audio/hal-demo.c

How CoreAudio HAL output works is like this:
- A audio callback is registered with the audio device
- Audio playback is started
- A separate thread, dedicated to audio processing, will then call the audio
callback with pre-allocated buffers to be filled out with audio samples.

The test program has "main" in C and the audio callback in C. The C callback
forwards to a Haskell routine exported by the FFI system. This routine
should behave identically to the C implementation that already exists.
However, the routine does not work correctly if called from the audio
thread.

The test program also calls the routine from the main thread in a manner
that should be identical to how it's called from the thread. This is used to
verify the Haskell callback does actually produce the same audio as the
original C callback. So I know the code should work, but just fails for some
inexplicable reason on the threaded callback.

Other notes:
- The program is compiled with -threaded and linked against the threaded
RTS.
- If I structure the routine like this:
    ...
    print "Before the audio is written to the buffer."
    process_frames
    print "After the audio is written to the buffer."

The first print succeeds but the second print never occurs. No IO error is
reported to try_.
- If I take that same structure and remove "pokeElemAt" from process_frames.
The second print occurs.

I've uploaded the test program here:
http://www.tothepowerofdisco.com/downloads/TestAudioOutput.zip

Some notes on if you actually try to build it:
- You have to build 3 times; There is a bug in XCode's custom build rule
handling or the projects custom build rule.
- The executable is wrapped in a app bundle but is actually a command line
app.
- It's a hack and I'm a beginner so comments are scarce and some code may be
strange. ;-)
- Assumes ghc 6.6 is installed to /usr/local

Any ideas?
-- 
-Corey O'Connor
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://www.haskell.org/pipermail/haskell-cafe/attachments/20070121/e30e2f4d/attachment.htm


More information about the Haskell-Cafe mailing list