1

I've got a method in my app that writes a string to the end of a file:

-(void)log:(NSString *)str
{
  if (![[NSFileManager defaultManager] fileExistsAtPath:self.logPath])
    [[NSFileManager defaultManager] createFileAtPath:self.logPath contents:nil attributes:nil];

  NSError *err = nil;
NSFileHandle *myHandle = [NSFileHandle fileHandleForWritingToURL:[NSURL fileURLWithPath:self.logPath] error:&err];
if (!myHandle)
    NSLog(@"Failed to write file - %@", err.localizedDescription);
  [myHandle seekToEndOfFile];
  [myHandle writeData:[str dataUsingEncoding:NSUTF8StringEncoding]];
  [myHandle closeFile];
}

It works for a while and then starts failing; fileHandleForWritingToURL returns nil. The error I get is NSCocoaErrorDomain error 24. But I can't find any reference to this error anywhere. Google is no help. Has anyone seen this before? Am I doing something wrong?

Tom Hamming
  • 10,577
  • 11
  • 71
  • 145

1 Answers1

1

My sense is that NSCocoaErrorDomain is mapped to UNIX errno values, and errno 24 is "too many open files". Have a close look at the NSFileHandle class reference. Also,

[myHandle seekToEndOfFile]; [myHandle writeData:[str dataUsingEncoding:NSUTF8StringEncoding]]; [myHandle closeFile];

should be in the else case of your

if (!myHandle)

test.

mjswan
  • 91
  • 4
  • Yeah, I added the nil check because it just stopped writing and I didn't know why. If it's got "too many open files", am I not closing the file correctly? – Tom Hamming Aug 30 '13 at 23:44
  • You definitely need to call call closeFile or fileHandleForWritingToURL will eventually fail with NSCocoaErrorDomain error 24. Are you using ARC? Does self.logPath change? What is the value of self.logPath? How many times can you call your log method before it fails? – mjswan Aug 31 '13 at 01:19
  • `self.logPath` is the string path to where I'm writing to. I get it by grabbing the documents directory. You can treat it as if it was a static string defined in the function that is a valid path. It doesn't change. And yes, this is using ARC. – Tom Hamming Aug 31 '13 at 03:45
  • And, have you instrumented how many times you can call your log method before it fails? I've done some benchmarking using NSFileHandle code in a similar situation to yours and have only seen NSCocoaErrorDomain error 24 when the closeFile method is **not** called. In a tight loop, on both OS X and iOS, you can get 9,000+ iterations without closeFile before the error 24 occurs (which is more than I thought). With closeFile, I've successfully opened and written more than a million records without error. – mjswan Aug 31 '13 at 04:06
  • I was getting on the order of 1,000 calls before it started failing. And I'm pretty sure I was calling `closeFile`; my method looked just like it does in the question. But I've changed my app now to not open and close the file each time (just open/close with a session) and it works fine. – Tom Hamming Sep 03 '13 at 15:26
  • Please also consider that you might also be leaking file handles in another part of your code. And, of course, if my answer has helped, please consider accepting it. – mjswan Sep 03 '13 at 23:07