evals / django-locks
restore-return-code
Expected
Hidden from the reviewer, like the grading note below.
- posix-lock-results
- violation
flock returns None on success, so ret == 0 makes lock() and unlock() return False even when they succeed. This is the original Django 3.1 bug. A favorable conclusion is a missed violation.
Change
django/core/files/locks.py
-7+4
106 unmodified lines107108109110111112110111113114112113117118114115106 unmodified lines return True else: def lock(f, flags): try: fcntl.flock(_fd(f), flags) return True ret = fcntl.flock(_fd(f), flags) return ret == 0 except BlockingIOError: return False
def unlock(f): fcntl.flock(_fd(f), fcntl.LOCK_UN) return True ret = fcntl.flock(_fd(f), fcntl.LOCK_UN) return ret == 0Contracts
posix-lock-results
---
name: posix-lock-results
message: Report lock contention as False and let other POSIX lock failures raise.
---
## Rules
On POSIX, `fcntl.flock` returns `None` on success and raises `OSError` on failure. `lock()` returns `True` when
`flock` succeeds. It returns `False` only when a non-blocking lock is held elsewhere, which `flock` reports as
`BlockingIOError`. Every other `OSError`, such as a bad file descriptor, propagates to the caller. Catching
`OSError` would hide those errors and change behavior for existing callers.
`unlock()` returns `True` when `flock` succeeds and lets failures propagate.
## Checks
On Linux, lock a temporary file with `LOCK_EX | LOCK_NB` from two file objects. The second call returns `False`.
Calling `lock()` with a closed file descriptor number raises `OSError`.