I was playing with the NSSound
class to play a sound in a background process of my own so as to not block user input. I decided to call fork()
but that is giving me problems. At the very moment the sound is allocated the forked process crashes. The funny thing is if I construct an example which only calls fork()
, then the child process can call NSSound
without problems, the crashes come only if I try to use other cocoa APIs before the fork()
call. See this example with the crashme?()
calls commented:
#import <AppKit/AppKit.h>
#import <math.h>
#define FILENAME
"/System/Library/Components/CoreAudio.component/"
"Contents/SharedSupport/SystemSounds/dock/drag to trash.aif"
void crashme1(void)
{
NSString *path = [[NSString alloc] initWithUTF8String:"false file"];
NSSound *sound = [[NSSound alloc]
initWithContentsOfFile:path byReference:YES];
}
void crashme2(void)
{
NSInteger tag = 0;
[[NSWorkspace sharedWorkspace]
performFileOperation:NSWorkspaceRecycleOperation
source:@"." destination:nil
files:[NSArray arrayWithObject:@"false file"] tag:&tag];
}
double playAif(void)
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSString *path = [[NSString alloc] initWithUTF8String:FILENAME];
NSSound *sound = [[NSSound alloc]
initWithContentsOfFile:path byReference:YES];
[path release];
if (!sound) {
[pool release];
return -1;
}
const double ret = [sound duration];
[sound play];
[sound autorelease];
[pool release];
return ret;
}
int main(int argc, char *argv[])
{
//crashme1();
//crashme2();
int childpid = fork();
if (0 == childpid) {
printf("Starting playback
");
double wait = playAif();
sleep(ceil(wait));
wait = playAif();
sleep(ceil(wait));
printf("Finished playback
");
}
return 0;
}
When I run this from the commandline it works, but if I uncomment one of the calls to either crashme?()
functions the playback in the forked process never starts. Is it because any of the Cocoa framework APIs are not async-signal safe? Is there any way to make the calls async signal safe by wrapping them somehow?