Skip to content

MutexImpl.unlock() hangs forever when locked through Semaphore.aquire() #4026

Closed
@lukellmann

Description

@lukellmann

The following code hangs forever on the call to mutex.unlock():

val mutex = Mutex()
(mutex as Semaphore).aquire()
println("locked: ${mutex.isLocked}")
mutex.unlock()
println("unlocked: ${!mutex.isLocked}")

The reason seems to be that MutexImpl extends SemaphoreImpl but SemaphoreImpl.aquire() bypasses the invariants of MutexImpl.owner: aquire doesn't change owner but unlock spin loops because it expects to see something different than NO_OWNER.

Similar bugs might be possible with other combinations of Mutex and Semaphore calls for MutexImpl, I haven't checked yet.

Admittedly, this is a bit contrived, so I'm not sure if this is really a bug or just a missuse of implementatiom details (the public Mutex interface doesn't extend Semaphore). But if this is considered worth fixing I see two possible approaches:

  • changing the behavior of the SemaphoreImpl methods (through override etc.) so they don't break MutexImpl invariants
  • splitting up SemaphoreImpl into a new abstract base type for both Mutex and Semaphore (that however doesn't implement Semaphore directly) and a thin wrapper around it to actually implement Semaphore - that way interacting with instances of MutexImpl through the methods of Semaphore won't be possible in the first place

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions