NSFileHandle Considered Harmful [Updated]
Update 20090627: This bug has been fixed in 10.6. I’d still only recommend using it for very simple cases, but at least it works now!
NSFileHandle has a bug where the calling thread will lock up indefinitely if a data of size >4096 is requested. Reduced case:
#import
int main (int argc, const char * argv[]) {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
NSFileHandle *fh = [[NSFileHandle alloc] initWithFileDescriptor:fileno(fopen("/dev/random", "r"))];
NSLog(@"Reading 4096 bytes... This will succeed.");
[fh readDataOfLength:4096];
NSLog(@"Reading 4097 bytes... This will lock for infinity");
[fh readDataOfLength:4097];
NSLog(@"This will never be printed.");
[fh closeFile];
[fh release];
[pool drain];
return 0;
}
(Warning: running this program might lock up your computer; killing the rogue process is difficult as NSFileHandle will read an infinite amount of data from /dev/random, swapping out your OS.)
This is extra dangerous if your read length is dynamic, such as in a protocol where the first incoming bytes defines how long the upcoming chunk to read is.
Solution: Use the C API for working with file descriptors instead, such as read() and write(). A file descriptor can be extracted with [NSFileHandle fileDescriptor] if you receive one from another API.