Skip to content

Commit

Permalink
Fix trying to infinitely acquire a lock if flock is not implemented
Browse files Browse the repository at this point in the history
  • Loading branch information
jahrules committed Mar 25, 2023
1 parent 745da61 commit 43472a5
Show file tree
Hide file tree
Showing 7 changed files with 41 additions and 16 deletions.
4 changes: 4 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,10 @@ repos:
hooks:
- id: tox-ini-fmt
args: ["-p", "fix"]
- repo: https://github.com/tox-dev/pyproject-fmt
rev: "0.9.2"
hooks:
- id: pyproject-fmt
- repo: https://github.com/PyCQA/flake8
rev: 6.0.0
hooks:
Expand Down
4 changes: 4 additions & 0 deletions docs/changelog.rst
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
Changelog
=========
v3.10.5 (2023-03-25)
--------------------
- Add explicit error check as certain UNIX filesystems do not support flock. by :user:`jahrules`.

v3.10.4 (2023-03-24)
--------------------
- Update os.open to preserve mode= for certain edge cases. by :user:`jahrules`.
Expand Down
32 changes: 17 additions & 15 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,10 @@ optional-dependencies.docs = [
optional-dependencies.testing = [
"covdefaults>=2.3",
"coverage>=7.2.2",
"diff-cover>=7.5",
"pytest>=7.2.2",
"pytest-cov>=4",
"pytest-mock>=3.10",
"pytest-timeout>=2.1",
]
urls.Documentation = "https://py-filelock.readthedocs.io"
Expand All @@ -56,6 +58,21 @@ build.hooks.vcs.version-file = "src/filelock/version.py"
build.targets.sdist.include = ["/src", "/tests"]
version.source = "vcs"

[tool.black]
line-length = 120

[tool.isort]
profile = "black"
known_first_party = ["filelock"]
add_imports = ["from __future__ import annotations"]

[tool.flake8]
max-complexity = 22
max-line-length = 120
unused-arguments-ignore-abstract-functions = true
noqa-require-code = true
dictionaries = ["en_US", "python", "technical", "django"]

[tool.coverage]
html.show_contexts = true
html.skip_covered = false
Expand All @@ -65,14 +82,6 @@ report.fail_under = 76
run.parallel = true
run.plugins = ["covdefaults"]

[tool.black]
line-length = 120

[tool.isort]
profile = "black"
known_first_party = ["filelock"]
add_imports = ["from __future__ import annotations"]

[tool.mypy]
python_version = "3.11"
show_error_codes = true
Expand All @@ -81,10 +90,3 @@ overrides = [{ module = ["appdirs.*", "jnius.*"], ignore_missing_imports = true

[tool.pep8]
max-line-length = "120"

[tool.flake8]
max-complexity = 22
max-line-length = 120
unused-arguments-ignore-abstract-functions = true
noqa-require-code = true
dictionaries = ["en_US", "python", "technical", "django"]
5 changes: 4 additions & 1 deletion src/filelock/_unix.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import os
import sys
from errno import ENOSYS
from typing import cast

from ._api import BaseFileLock
Expand Down Expand Up @@ -39,8 +40,10 @@ def _acquire(self) -> None:
pass # This locked is not owned by this UID
try:
fcntl.flock(fd, fcntl.LOCK_EX | fcntl.LOCK_NB)
except OSError:
except OSError as exception:
os.close(fd)
if exception.errno == ENOSYS: # NotImplemented error
raise NotImplementedError("FileSystem does not appear to support flock; user SoftFileLock instead")
else:
self._lock_file_fd = fd

Expand Down
10 changes: 10 additions & 0 deletions tests/test_filelock.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import sys
import threading
from contextlib import contextmanager
from errno import ENOSYS
from inspect import getframeinfo, stack
from pathlib import Path, PurePath
from stat import S_IWGRP, S_IWOTH, S_IWUSR, filemode
Expand All @@ -14,6 +15,7 @@

import pytest
from _pytest.logging import LogCaptureFixture
from pytest_mock import MockerFixture

from filelock import (
BaseFileLock,
Expand Down Expand Up @@ -494,3 +496,11 @@ def test_wrong_platform(tmp_path: Path) -> None:
lock.acquire()
with pytest.raises(NotImplementedError):
lock._release()


@pytest.mark.skipif(sys.platform == "win32", reason="flock not run on windows")
def test_flock_not_implemented_unix(tmp_path: Path, mocker: MockerFixture) -> None:
mocker.patch("fcntl.flock", side_effect=OSError(ENOSYS, "mock error"))
with pytest.raises(NotImplementedError):
with FileLock(str(tmp_path / "a.lock")):
pass
1 change: 1 addition & 0 deletions tox.ini
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ commands =
--cov-config=pyproject.toml --no-cov-on-fail --cov-report term-missing:skip-covered --cov-context=test \
--cov-report html:{envtmpdir}{/}htmlcov --cov-report xml:{toxworkdir}{/}coverage.{envname}.xml \
tests}
diff-cover --compare-branch {env:DIFF_AGAINST:origin/main} {toxworkdir}{/}coverage.{envname}.xml
package = wheel
wheel_build_env = .pkg

Expand Down
1 change: 1 addition & 0 deletions whitelist.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ autodoc
autosectionlabel
caplog
eacces
enosys
extlinks
filelock
filemode
Expand Down

0 comments on commit 43472a5

Please sign in to comment.