I'm trying to compress a file using /usr/bin/compress, launched with no file name so that it takes data from stdin and writes compressed data to stdout. I create the task with pipes for standardInput, Output & Error. In a loop, I read a block of data from the file, write to the task's stdin, then read from stdout using [NSFileHandle availableData]. I've tried block sizes of 2K, 8K and 12K. In all cases, my program just hangs. I am targeting for 10.6
The way my code is structured, I prefer it to block on availableData since I can't do anything until the data arrives and the caller expects return only when processing is complete. So far this is all in the main thread. Once it works, I'll move this part to a separate thread so as not to block the main, and yes, I will then need to make the caller accept an asynchronous completion once the subordinate thread exits.
init
{
self = [super init];
if (self) {
task = [[NSTask alloc] init];
NSPipe* stdin_Pipe = [NSPipe pipe];
NSPipe* stdoutPipe = [NSPipe pipe];
NSPipe* stderrPipe = [NSPipe pipe];
[task setStandardInput: stdin_Pipe];
[task setStandardOutput: stdoutPipe];
[task setStandardError: stderrPipe];
[task setLaunchPath: kCompressor];
NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
[nc addObserver: self
selector: @selector (taskTerminated:)
name: NSTaskDidTerminateNotification
object: task];
[task launch];
}
return self;
}
Write some, read some. Nothing says when compress will decide to write.
(NSData*) compressData: (NSData*) source
{
[[[task standardInput] fileHandleForWriting] writeData: source];
return [[[task standardOutput] fileHandleForReading] availableData];
}
... and the code that uses the previous snippets:
(BOOL) compressFile: (NSString*) file
{
//...
NSData* fileDataBlock = [sourceFileHandle readDataOfLength: kTargetFileReadBlockLen];
while ( [fileDataBlock length] > 0) {
NSData* compressedData = [origFileCompress compressData: currentBuffer];
//...
}
}
gdb shows my program doing this (newest frame first):
0x9a0ade5e in read$UNIX2003
0x91ebcc13 in _NSReadFromFileDescriptor
0x91ec3c64 in -[NSConcreteFileHandle availableData]
0x00002e8b in -[Compress compressData:] at CompressIt.m:266
While Activity Monitor --> Sample Process shows /usr/bin/compress doing this (oldest frame first):
2672 fread (in libSystem.B.dylib) + 436 [0x7fff8a0e501a]
2672 __srefill1 (in libSystem.B.dylib) + 27 [0x7fff8a0e50a5]
2672 _sread (in libSystem.B.dylib) + 19 [0x7fff8a0dce34]
2672 __sread (in libSystem.B.dylib) + 16 [0x7fff8a0e50ef]
2672 read$NOCANCEL (in libSystem.B.dylib) + 10 [0x7fff8a095982]