Finder File Previews lock files on SMB shares

I've developed a new Quicklook data-based preview extension for a custom file type that generates an image preview of the file. I previously used a Quick Look generator plug-in but support for it was deprecated and now removed in macOS Sequoia.

My app opens files using a

open(url.path, O_RDWR | O_NONBLOCK | O_EXLOCK)

call. The locking flags are used to prevent other clients from writing the file if it's already open.

I discovered that when Finder is showing the “large” file previews (such as when in column or gallery modes) from a SMB share, the open call fails with EWOULDBLOCK as if the file is locked.

It does work just fine on local files. Opening with O_SHLOCK also has the issue. Surprisingly it does work just fine for previews that return Plain Text data instead of Image data.

Using the lsof command, it seems like the Quicklook process has some kind of lock on the file. This is the output of the lsof command:

COMMAND     PID    USER   FD   TYPE DEVICE  SIZE/OFF    NODE
QuickLook   48487  XXXX   txt  REG  1,15    125000611   3161369 

Attached is a test project that tries a few different opening and locking functions. It also includes a test file and a sample image preview extension that displays a red square.

When everything is working, regular console messages show the progress of the tests. When the file is on a SMB share and selected in Finder Gallery mode, the open test will fail with a fault message in the console.

Notably, locking with flock works, which is weird because it should have similar semantics according to the man page for open(2).

Filed this as FB15051186

Can you try to use File Coordination instead of O_EXLOCK, or is the EXLOCK specifically used because some apps are not File Coordination-compliant?

My app opens files using a open(url.path, O_RDWR | O_NONBLOCK | O_EXLOCK)

call. The locking flags are used to prevent other clients from writing the file if it's already open.

So, unfortunately, I think the best recommendation I can give here is "give up" on the idea that you can prevent other clients from writing to the the file while it's open. Relying on file locking for this sort of case tends to convert the broad design problems of "don't crash on bad input" and "what should I do if the file I'm thumbnailing changes" into an unending stream of edge case failures. There's a few reasons for that.

On the file system itself side:

  1. Advisory locking adoption is sufficiently low that lots of apps are just going to ignore it.

  2. How locking will ACTUALLY behave across a range of file sharing systems is... difficult to predict. The combination of divergent behavior across operating systems, file sharing servers, and protocols make this entire area pretty broken.

Similarly, on the actual file side:

Note: when I talk in terms of "size" below, this really refers to the combination of file size AND network perfromance. So a physically "large" file is "smaller" on a fast network, while a physically "small" file is "larger" on a slow network.

  1. If the file is "small", then locking doesn't really matter. It's unlikely the file changed while you were reading it and, if it did, you could just rescan the file.

  2. If the is "large", then locking very well could matter... and not it a good way. If the lock works the way you want/expect, then your lock means the user is going to block the user from opening the file at exactly the time they wanted to.

  3. For most macOS apps, none of this matters anyway. Most macOS apps implement "safe save" semantics, which will (mostly) bypass file locking. Note that everything except the first copy will bypass file locking.

  • Copy the original file to a secondary location on the same volume.

  • Modify that copy.

  • Swap (ideally, atomically) the original and the copy.

  • Delete the original.

This recommendation might have some value:

Can you try to use File Coordination instead of O_EXLOCK, or is the EXLOCK specifically used because some apps are not File Coordination-compliant?

...but that's primarily because of how it improves interactions with compliant apps, not because it will change anything about the larger issue.

__
Kevin Elliott
DTS Engineer, CoreOS/Hardware

Hi @DTS Engineer (Kevin).

Thanks for your detailed reply.

I will add a bit more context to explain how our app uses locking and why. I realized from your answer that it may be different that the common use case.

The app locks the file with an exclusive lock when the user opens the file to begin editing it. The file will stay locked as long as it is open.

The main goal is to signal other instances of our app on other machines that the file is already open if another user tries to open and edit the same file. We do not want users to start working on a file that someone else may have started working on already and that may have unsaved changes.

We are not really interested in preventing other apps from modifying the file because that will rarely happen in our usage scenarios.

We do need to support Windows clients connected to networks shares since our app is cross-platform. Our team has in fact proved in the past that open(url.path, O_RDWR | O_NONBLOCK | O_EXLOCK) does work over SMB shares and we're reluctant to switch to a totally different locking system.

We also have to keep supporting older app versions that use open.

Given this additional information, do you think there's anything we can do to address the issue? Also, why does having a plain-text preview vs an image one affect the Quicklook locking behavior (and it's impact on us)?

Alberto

First off, jumping back to here:

Using the lsof command, it seems like the Quicklook process has some kind of lock on the file. This is the output of the lsof command:

Have you tried sampling (with Activity Monitor) the Quicklook process when it's in this state? I'd like to see if it's idled again or if it thinks it's doing something useful.

We do need to support Windows clients connected to networks shares since our app is cross-platform. Our team has in fact proved in the past that open(url.path, O_RDWR | O_NONBLOCK | O_EXLOCK) does work over SMB shares and we're reluctant to switch to a totally different locking system.

OK. My main warning here is that, in my experience, belief in how well this work is directly proportional to how broad the testing process has been.

Given this additional information, do you think there's anything we can do to address the issue?

I don't know. The immediate thing I would try here is changing what's your actually doing/returning, both by either using the "draw" reply option or by writing your return data to a file and returning that.

Also, why does having a plain-text preview vs an image one affect the Quicklook locking behavior (and it's impact on us)?

Basically, they're just totally code paths. I haven't looked at the full paths in detail, but I suspect the text is being returned back for "direct" display, while the image data end up being resized or otherwise altered.

__
Kevin Elliott
DTS Engineer, CoreOS/Hardware

Hi @DTS Engineer,

Thank you for your assistance and support.

Regarding the issue of a file being exclusively locked by Quick Look Extension Preview, I believe this might be an oversight. Here are some points to consider:

  1. Prior to macOS 15, the Quick Look Generator Preview functioned without this issue. However, the Quick Look Extension Preview exhibits this problem.
  2. In the Quick Look Extension system, thumbnail generation works without issue, but preview generation does not.
  3. As Alberto pointed out, text previews are unaffected, whereas image previews are impacted.
  4. Quick Look does not seem to require an exclusive lock on a file for reading purposes.

Given these observations, it seems likely that the exclusive lock behavior in the Quick Look Extension Preview, when accessing files over SMB, in unintentional.

If this is not an oversight, could you kindly explain why an exclusive lock is necessary in the Quick Look Extension Preview? This insight would help us better understand the situation and explore alternative solutions.

Thank you again for your continued support!

Best regards, Payne

Finder File Previews lock files on SMB shares
 
 
Q