Skip to content

SmartLock hangs on recursive acquire from the same thread #28

Description

@pomponchik

SmartLock deadlocks when the same thread tries to acquire the same lock twice. The deadlock is not reported as an exception, so code using SmartLock for deadlock detection can still hang on this self-recursive case.

Reproduction

from threading import Thread

from locklib import SmartLock

events = []


def target():
    lock = SmartLock()
    lock.acquire()
    events.append('first acquire returned')
    lock.acquire()
    events.append('second acquire returned')


thread = Thread(target=target, daemon=True)
thread.start()
thread.join(0.3)

print(thread.is_alive())
print(events)

Current output:

True
['first acquire returned']

Expected behavior

The second acquire should not block forever. SmartLock should report this deadlock case instead of leaving the thread stuck.

Actual behavior

The second acquire never returns, and no exception is raised.

Proposed solution

Reproduce the semantics of standard Python locks by replacing the current single SmartLock class with two classes:

  • SmartLock: raises an exception when the same thread tries to acquire the same lock recursively. This behavior needs to be added.
  • SmartRLock: behaves like SmartLock in every other respect, but differs in this case: recursive acquire by the same thread does not raise and simply does nothing.

As an optional way to reduce duplication, introduce a shared base class named AbstractSmartLock in locklib/locks/smart_lock/abstract.py. Move the current SmartLock logic there, make the recursive-acquire behavior conditional on a class-level recursive flag, and make SmartLock and SmartRLock inherit from it with bodies containing only recursive = False and recursive = True, respectively.

Context

  • locklib: 0.0.23
  • Python: 3.8.10
  • OS: macOS / Darwin 24.3.0

Metadata

Metadata

Assignees

Labels

bugSomething isn't working

Type

No type

Fields

No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions