Skip to content

calling both mutex.acquire() and mutex.waitForUnlock() on a locked mutex will cause a deadlock #88

@thevolp

Description

@thevolp

It's a bit of an edge case, but I couldn't find anything in the documentation that explicitly forbids this behavior.

The use case involves a wrapper around Mutex to manage parent/child locks on resource trees: when a child is locked, any attempt to lock its parent must wait until the child lock is released and viceversa.

In this implementation, it's possible for two or more lock requests to target the same parent/child tree, in which case the existing Mutex instance will be reused.

This leads to the issue:

  • The first request acquires the lock.
  • The second request ends up both waiting for the current lock to release (waitForUnlock()) and trying to acquire the lock (acquire()).

As a result it seems the second request deadlocks, since it's simultaneously waiting for the lock to release and trying to acquire it, causing the program to hang.

   import { Mutex } from 'async-mutex';
 
   const mtx = new Mutex();

    const release = await mtx.acquire();

    setTimeout(() => {
      release();
    }, 1000);

    await Promise.all([
      mtx.acquire(),
      mtx.waitForUnlock(),
    ]);

    // will never reach here
  
   console.log('done');
   mtx.release()

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions