Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

FileNotFoundError: [Errno 2] No such file or directory: '/tmp/locks/my_lock.lock' #176

Closed
connormason opened this issue Nov 30, 2022 · 12 comments · Fixed by #254
Closed

Comments

@connormason
Copy link

I have been intermittently seeing this error (was thinking possibly due to a race condition), but one of my coworkers started running into this issue repeatedly. Any idea why this could be happening? Reproducing solely on macOS

Code I'm running:

lock_path = '/tmp/locks/my_lock.lock'
with FileLock(lock_path, timeout=0):
   ... 

I see that in _acquire() the os.O_CREAT flag is being provided to os.open(), so shouldn't the file be created if it does not exist?

Sanitized traceback:

Traceback (most recent call last):
  File "/Users/my_user/.virtualenvs/my_proj/my_proj/cache.py", line 311, in update_cache
    with FileLock(lock_path, timeout=0):
  File "/Users/my_user/.virtualenvs/my_env/lib/python3.10/site-packages/filelock/_api.py", line 220, in __enter__
    self.acquire()
  File "/Users/my_user/.virtualenvs/my_env/lib/python3.10/site-packages/filelock/_api.py", line 173, in acquire
    self._acquire()
  File "/Users/my_user/.virtualenvs/my_env/lib/python3.10/site-packages/filelock/_unix.py", line 35, in _acquire
    fd = os.open(self._lock_file, open_mode)
FileNotFoundError: [Errno 2] No such file or directory: '/tmp/locks/my_lock.lock'
@gaborbernat
Copy link
Member

It should, there must be something else going on, never seen this myself. A repro with a docker image would be nice...

@shughes-uk
Copy link

Also running into this on macos, python 3.10.8

@gaborbernat
Copy link
Member

Does some other process delete the lock? Generally, it's not a great practice to have lock files under /tmp for that reason.

@shughes-uk
Copy link

shughes-uk commented Dec 7, 2022

For me the lock is not in a temporary directory

FileNotFoundError: [Errno 2] No such file or directory: 'file:/Users/samanthahughes/programming/cloud/python-api/.build.lock'

A quick ls -la /Users/samanthahughes/programming/cloud/python-api show it exists and is a directory

@gaborbernat
Copy link
Member

PR welcome 🤔 perhaps we should do a mkdir on the parent of the file to ensure that folder exists at the time of creation 🤔 could also be a permission issue, and Python surfaces it with this FileNotFoundError; we would need to investigate if you can replicate. Otherwise, a docker image doing that would be helpful.

@shughes-uk
Copy link

shughes-uk commented Dec 7, 2022 via email

@TheMatt2
Copy link
Contributor

By chance, this isn't Mac OS X Leopard, and a known OS issue that could cause a FileNotFoundError? (Patched 2011) http://www.weirdnet.nl/apple/rename.html

@jahrules
Copy link
Contributor

I don't have access to an osx box to test this, but I wonder if the unix behavior of emptying tmp was retained in osx and perhaps they're also deleting the folder inside of tmp? Just a thought

@TheMatt2
Copy link
Contributor

TheMatt2 commented Mar 24, 2023

I don't have access to an osx box to test this, but I wonder if the unix behavior of emptying tmp was retained in osx and perhaps they're also deleting the folder inside of tmp? Just a thought

On my osx box, I can confirm that osx does retail the unix behavior of emptying tmp.
The current shell script used (as of MacOS 12.6.3) can be found here: https://opensource.apple.com/source/crontabs/crontabs-52/files/daily/110.clean-tmps.auto.html

I can confirm that osx will delete folders in /tmp after 72 hours of inactivity, and only if all files within them have a creation time of over 72 hours.

Considering this is a "repeated" issue, I'm thinking the MacOS expiring behavior may not be the issue. tmp is cleared on reboot, and this is the error you would expect if /tmp/locks did not exist.

Is it possible rebooting is causing the error?

Related Stack post: https://superuser.com/questions/187071/in-macos-how-often-is-tmp-deleted

@jahrules
Copy link
Contributor

yeah I would definitely agree that reboot is involved. This is the same behavior as other Unix derivatives.

If the folder inside of /tmp/ is part of some image or a docker; then it is very possible that the folder creation date is tagged as when the image was created which could cause the folder to be immediately flagged and deleted upon startup of the image/instance.

I think that using /tmp/ for locks is a deeply bad practice; I could see two routes. check for directory existence and do a mkdir if needed; or instead throw a clearer error to tell the user that their subdirectory is missing.

I personally prefer the second as I worry about side effects of automatic directory creation when a user isn't expecting it - particularly if there are symlinks, hardlinks, remote filesystems, etc involved. I just think that might be a big can of worms that we don't want to get involved in.

@TheMatt2
Copy link
Contributor

TheMatt2 commented Mar 24, 2023

then it is very possible that the folder creation date is tagged as when the image was created which could cause the folder to be immediately flagged and deleted upon startup

To clarify, on MacOS folders are checked for deletion by modification time, not creation. Every time a file is created, the modification time is updated. Except...

filelock does not actually delete the lock on release on MacOS (I see there have been contention over this, but I am still not sure of the nuance of lock deletion on unix). This means that the file is only created once, and so the folder modification time is only updated once. Even if the lock continues to be used after that, it will not update the creation time of the lock, nor the modification time of the folder. As such, both will be deleted by the system ~72 hours after initial use.

The solution is for the application code to create the directory if it doesn't exist. @connormason is it possible this could be the solution?

I don't actually think using /tmp for locks is a bad idea, if what you want is a lock that is deleted in system reboot.
However, you want to handle this error by making the directory.

I see that in _acquire() the os.O_CREAT flag is being provided to os.open(), so shouldn't the file be created if it does not exist?

Just to answer your question. Yes, passing os.O_CREAT to the file should create the file, unless the directory doesn't exist. In which case you will get FileNotFoundError, (and I'm fairly certain the lack of the directory is the only way to get a FileNotFoundError on attempted file creation).

@zhouaihui
Copy link

Well, i ran into this issue and solved it.
The reason is that dir /tmp/locks/ not exists, you can make the dir to ensure os.O_CREAT works.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

6 participants