DirtyHairy / async-mutex

A mutex for synchronizing async workflows in Javascript
MIT License
1.14k stars 63 forks source link

Race condition when using runExclusively #44

Closed trajano closed 3 years ago

trajano commented 3 years ago

I have the runExclusively code and the acquire method and I found that the runExclusively sometimes misses the lock at least on android.

image

Here's a snack that you can use to test it out. It's very random.

https://snack.expo.io/@trajano/sqlite-transaction-block

But so far I haven't been able to do it on the acquire. release style.

DirtyHairy commented 3 years ago

HI @trajano !

Sorry, I don't seem to be able to access the console in the virtual devices linked in the snack. However, I see two problems with your code:

  1. You create a new instance of the mutex each time the component renders. Thus, a rerender between calls to your handlers will create a new mutex, and the async code in the handlers can interleave. You should either wrap the mutex in useRef or use a module-global instance.
  2. You execute await mutex.lock() before your call to mutex.runExclusive() and never release the lock. This means that the mutex stays locked, and the code wrapped in runExclusive never executes. This consistent with your log messages, which seem to originate from startMutexTxn() (and not startMutexTxn2).
trajano commented 3 years ago

Thanks let me fix it I think it was a left over copy and paste. Though it was an await mutex.acquire() not lock() I'll revert it back to use a useRef to prevent the re-renders. Mind you with the supposed rerenders it also works (not I don't think the code rerenders anyway because I write the output to the logs).

Logs are here image then image

However, like I said it's hard to replicate. Anyway closing this for now but we can probably re-open in case someone else has an issue at least the snack is there to help replicate the issue.

DirtyHairy commented 3 years ago

Thanks for the pointer to the console, hiding in plain sight. I can observe the same phenomenon in the log as you, so it superficially looks like the lock is not taking effect, but look what happens after adding a timestamp to the log:

image

(the timestamp is the second number, the first one is an instance ID that I added to the mutex in order to make sure that this is not some weird effect of hot reloading). Both logs a separated by ~2000 msec, as expected. This is just an output issue, it seems that the console sometimes misses updates.