调试Mac/Cocoa文件描述符泄漏



我的沙盒Mac应用程序(显然)泄漏文件资源(句柄?)在向它添加文件(并将其中一些文件转换为不同的格式)时,它将在-[NSFileManager copyItemAtPath:toPath:error:]上失败,并出现以下底层错误:

NSUnderlyingError=0x600000440a50 "The operation couldn’t be completed. Too many open files"

我可以可靠地复制这个Xcode外部(与调试构建),但从来没有在内部。看起来某个地方的文件一直在打开,但从未关闭。每次当我删除同一个文件夹时,它都会发生在同一个文件上,或者当我取出那个文件时,它会发生在下一个文件上。我记录了我能想到的在NSFileManager之外做文件I/O的每个地方,看起来我所有的开放调用都与关闭平衡,就像我在NSURLs上启动和停止安全资源访问的调用一样。

    为什么这不会发生在Xcode内部?
  1. 如何追踪不平衡呼叫发生的位置?
  2. 错误是否可能是转移注意力?

我试着在Xcode以外的仪器中运行文件活动预设,并能够再现其中的错误,但它看起来不像有任何方法可以从所使用的仪器(文件活动,读/写,文件属性,目录I/O)中获得我需要的信息。

我最终通过仪器找到了根本原因。我根据FD列对File Attributes instrument的事件列表进行了排序,并且能够看到对于相同的文件描述符有许多"打开"事件(有些对于相同的文件和不同的描述符),没有任何"关闭"事件。我可以追踪到我使用的一个库中的违规代码。我在单元测试中复制了它,使用这种方法并比较了一些代码运行前后的情况:

- (NSInteger)numberOfOpenFileHandles {
    int pid = [[NSProcessInfo processInfo] processIdentifier];
    NSPipe *pipe = [NSPipe pipe];
    NSFileHandle *file = pipe.fileHandleForReading;
    NSTask *task = [[NSTask alloc] init];
    task.launchPath = @"/usr/sbin/lsof";
    task.arguments = @[@"-P", @"-n", @"-p", [NSString stringWithFormat:@"%d", pid]];
    task.standardOutput = pipe;
    [task launch];
    NSData *data = [file readDataToEndOfFile];
    [file closeFile];
    NSString *lsofOutput = [[NSString alloc] initWithData: data encoding: NSUTF8StringEncoding];
//    NSLog(@"LSOF:n%@", lsofOutput);
    return [lsofOutput componentsSeparatedByCharactersInSet:[NSCharacterSet newlineCharacterSet]].count;
}

相关内容

  • 没有找到相关文章

最新更新