权限被拒绝,由 NSURL 资源泄漏引起?
Permission denied, caused by an NSURL resource leak?
我的 Mac 应用会复制用户拖入的文件。该应用是沙盒化的。我现在有一个错误,我可以在 Xcode 中可靠地重现它,但我无法追踪它的来源。
当我添加一定数量的文件时,应用程序突然无法访问后面的文件。所有源文件都从同一父目录向下一级,并且其间的所有文件夹都具有相同的权限,已通过 ls -l
验证。该应用保留了 Destination Directory
的应用范围书签,在创建 .directoryName
和开始文件复制之前访问该书签。
我收到错误:
Error Domain=NSCocoaErrorDomain Code=513 "“Filename.ext” couldn’t be copied because you don’t have permission to access “.directoryName”." UserInfo=0x6080000eaf80 {NSSourceFilePathErrorKey=/Users/Username/Parent Directory/Subdir/Filename.ext, NSUserStringVariant=(
Copy
), NSDestinationFilePath=/Users/Username/Desktop/Destination Directory/.directoryName/Filename.ext, NSFilePath=/Users/Username/Parent Directory/Subdir/Filename.ext, NSUnderlyingError=0x6080004567a0 "The operation couldn’t be completed. Operation not permitted"}
我在调试时做了以下操作:
- 尝试在退出并重新启动后自行添加
Subdir/Filename.ext
,效果很好
- 已验证(使用
lsof
和 Activity 监视器)我没有泄漏文件句柄(我知道这在过去对我造成了类似的问题)
- 已使用符号断点验证每次对
-[NSURL startAccessingSecurityScopedResource]
的调用都与对 -[NSURL stopAccessingSecurityScopedResource]
(及其 CF
等价物)的调用保持平衡
- 确定
Filename.ext
和其他失败的文件在没有其他文件的情况下添加成功
- 在调试器内部和外部,调试和发布版本会出现相同的行为
- 我尝试 运行ning 作为 root,但我的应用程序不会 运行 这样。当在调试器中 运行ning 时,我得到一个
EXC_BAD_INSTRUCTION
异常,并且在命令行上 运行ning 它与 sudo
产生崩溃(可能是同一个)
该行为似乎表明存在某种资源泄漏,但我还没有检测到。知道还有什么可能导致这种情况吗?
更新
我还没准备好宣布答案,但在用户将文件放入应用程序后,我的代码的不同部分开始出现这些权限错误。我注意到在日志的上方,我会看到如下消息:
Consume sandbox extension for itemIdentifier (1) from pasteboard failed!
追踪这个错误让我想到了其他人提出的问题:Sandboxed Mac app exhausting security scoped URL resources
不幸的是,accepted answer 说(释义)"tough noogies"。似乎 Cocoa 和沙盒机制本身正在泄漏安全范围令牌(尽管我无法使用符号断点进行验证并且不知道其他检查方法)。在对沙盒文件进行一定数量(未知)的文件操作后,您将开始收到此错误,唯一的解决办法是退出并重新启动。
我希望至少有一些方法可以在关闭时提示用户重新启动,但我不确定是否有任何方法可以衡量这些句柄中有多少正在使用。或者,更好的是,如果我可以在处理完删除的文件后手动清理,但我不确定这将如何工作,因为我需要使用 NSFilenamesPboardType
粘贴板类型来获取多个文件的路径。我尝试从这些创建 NSURL
s 并停止安全范围访问,但这没有效果。
更新 2
我为此提交了 DTS 票证,因为它影响了用户并且没有明确的解决方法。当我发现更多时,我会更新问题(也许会给出答案?)。
苹果DTS团队的回应
显然,这是一个已知问题,没有可用的解决方法。我提交了雷达:rdar://20652066,如果你想欺骗它。
这已在 El Capitan (10.11) 版本中修复(可能是第一个,但我不确定)。当我根据更新后的 SDK 构建我的应用程序时,行为恢复正常。
我的 Mac 应用会复制用户拖入的文件。该应用是沙盒化的。我现在有一个错误,我可以在 Xcode 中可靠地重现它,但我无法追踪它的来源。
当我添加一定数量的文件时,应用程序突然无法访问后面的文件。所有源文件都从同一父目录向下一级,并且其间的所有文件夹都具有相同的权限,已通过 ls -l
验证。该应用保留了 Destination Directory
的应用范围书签,在创建 .directoryName
和开始文件复制之前访问该书签。
我收到错误:
Error Domain=NSCocoaErrorDomain Code=513 "“Filename.ext” couldn’t be copied because you don’t have permission to access “.directoryName”." UserInfo=0x6080000eaf80 {NSSourceFilePathErrorKey=/Users/Username/Parent Directory/Subdir/Filename.ext, NSUserStringVariant=( Copy ), NSDestinationFilePath=/Users/Username/Desktop/Destination Directory/.directoryName/Filename.ext, NSFilePath=/Users/Username/Parent Directory/Subdir/Filename.ext, NSUnderlyingError=0x6080004567a0 "The operation couldn’t be completed. Operation not permitted"}
我在调试时做了以下操作:
- 尝试在退出并重新启动后自行添加
Subdir/Filename.ext
,效果很好 - 已验证(使用
lsof
和 Activity 监视器)我没有泄漏文件句柄(我知道这在过去对我造成了类似的问题) - 已使用符号断点验证每次对
-[NSURL startAccessingSecurityScopedResource]
的调用都与对-[NSURL stopAccessingSecurityScopedResource]
(及其CF
等价物)的调用保持平衡 - 确定
Filename.ext
和其他失败的文件在没有其他文件的情况下添加成功 - 在调试器内部和外部,调试和发布版本会出现相同的行为
- 我尝试 运行ning 作为 root,但我的应用程序不会 运行 这样。当在调试器中 运行ning 时,我得到一个
EXC_BAD_INSTRUCTION
异常,并且在命令行上 运行ning 它与sudo
产生崩溃(可能是同一个)
该行为似乎表明存在某种资源泄漏,但我还没有检测到。知道还有什么可能导致这种情况吗?
更新
我还没准备好宣布答案,但在用户将文件放入应用程序后,我的代码的不同部分开始出现这些权限错误。我注意到在日志的上方,我会看到如下消息:
Consume sandbox extension for itemIdentifier (1) from pasteboard failed!
追踪这个错误让我想到了其他人提出的问题:Sandboxed Mac app exhausting security scoped URL resources
不幸的是,accepted answer 说(释义)"tough noogies"。似乎 Cocoa 和沙盒机制本身正在泄漏安全范围令牌(尽管我无法使用符号断点进行验证并且不知道其他检查方法)。在对沙盒文件进行一定数量(未知)的文件操作后,您将开始收到此错误,唯一的解决办法是退出并重新启动。
我希望至少有一些方法可以在关闭时提示用户重新启动,但我不确定是否有任何方法可以衡量这些句柄中有多少正在使用。或者,更好的是,如果我可以在处理完删除的文件后手动清理,但我不确定这将如何工作,因为我需要使用 NSFilenamesPboardType
粘贴板类型来获取多个文件的路径。我尝试从这些创建 NSURL
s 并停止安全范围访问,但这没有效果。
更新 2
我为此提交了 DTS 票证,因为它影响了用户并且没有明确的解决方法。当我发现更多时,我会更新问题(也许会给出答案?)。
苹果DTS团队的回应
显然,这是一个已知问题,没有可用的解决方法。我提交了雷达:rdar://20652066,如果你想欺骗它。
这已在 El Capitan (10.11) 版本中修复(可能是第一个,但我不确定)。当我根据更新后的 SDK 构建我的应用程序时,行为恢复正常。