Tuesday, December 3, 2019

Reading the Resource Fork Too Often

Mark Alldritt:

This problem happens after a document has been opened in Script Debugger and changes have been saved a number of times. If the saves are done in fairly quick succession, Script Debugger will begin reporting that it cannot save document changes. In some instances, errors -54 (permErr) or -43 (fnfErr) are reported. Additionally, once this situation arises and you close the document, it is no longer possible to open the effected document in Script Debugger.


At a technical level, the problem is triggered when applications attempt to read the resource fork of a document repeatedly within a given period of time. This behaviour by an application seems to trigger a security mechanism within Catalina that prevents further access to the document’s resource fork (the resource fork is used to retain meta-data in text and compiled AppleScript documents).

You’d think that old deprecated stuff like resource forks would just keep working in its frozen state. But both Mojave and Catalina introduced resource bugs that have hit my apps. There are more modern replacements for many uses of the resource fork, but they don’t always work. And, as with the AppleScript example, sometimes the resource fork is unavoidable, and the problems even hit Apple’s own apps.


Update (2019-12-12): Howard Oakley:

With Shane Stanley’s help, I’ve been able to reproduce this problem and to examine an excerpt of the log detailing what happened on that occasion. In this case, trying to access a resource fork in an AppleScript .scpt file which had just been repeatedly edited using Apple’s Script Editor triggered a request to the Catalina privacy system (TCC), which required the requesting app to have been granted a kTCCServiceSystemPolicyAllFiles entitlement.


One way to avoid that particular error is to add apps which need access to resource forks, like Script Debugger and Script Editor, to the Full Disk Access list in the Privacy tab of the Security & Privacy pane.

Peter Steinberger:

„After macOS 10.10, our users reported weird new crashers. As if the lock method in NSPersistentStoreCoordinator didn’t do anything anymore. Let’s look into Hopper... oh. [the lock was gone, method just was a NOP]

It’s not safe to rely on deprecated methods.

8 Comments RSS · Twitter

Thank you, Michael and Mark. I've been trying to reproduce this bug by writing and reading xattrs repeatedly in both Mojave and Catalina, and can't trigger it using com.apple.metadata:kMDItemCreator even after more than 20 quite rapid write-read cycles, performed from Swift code. Are there any more specific clues as to what is needed to trigger it, please?

@Howard xattrs aren’t stored in the resource fork.

@Howard Use com.apple.ResourceFork.

I think that you'll find that the Resource Fork has been implemented as an extended attribute for quite some time now.
Accessing it through the com.apple.ResourceFork interface as a xattr, I'm still unable to reproduce this bug: I can write and read that xattr in rapid succession for more than 20 cycles without experiencing any problems.
Could the problem rest in the interface that's being used rather than the file system itself, perhaps?

Shane Stanley

@Howard, when the bug is triggered you can still read and write extended attributes, including com.apple.ResourceFork. The blocking only occurs when you use resource fork APIs, or try reading using /..namedfork/rsrc (which both appear to end up calling __open in libsystem_kernel.dylib, where the problem occurs). Console shows blocking is done by sandboxd, even though it's happening with non-sandboxed apps.

Thank you, Shane.
I'm out most of today with a funeral, but will try to replicate this in my test app using the same calls as soon as I get a chance.

I've just had a chance to try this in Swift, on both Mojave and Catalina.
What my test app does is create the com.apple.ResourceFork xattr with a small section of UTF-8 text when it opens the test file. The test procedure then reads that as a resource fork, using
NSData.init(contentsOfFile: (self.theSourcePath + "/..namedfork/rsrc"))
which is as close as Swift will come without calling more 'alien' functions direct.
I can run barrages of those reads, up to 50 in rapid succession, without encountering any error.
This looks like a specific API problem, rather than something inherent using the traditional way of accessing resource forks.

Shane Stanley

Just to be clear, the exact triggering of the bug is more complex repeated attempts to read a resource fork; there's clearly more going on. But it occurs in cases *where* repeated attempts to read a resource fork are made.

Leave a Comment