Closed pipobscure closed 9 years ago
Ok, I found it.
libuv has the number of worker_threads that a loop has set to 4. This leads to only 4 blocking operations being possible at the same time in a loop. When there are 5 calls to flock, then the first succeeds, and the next 4 fill up the worker threads and block them all. Even though flock('un') is then called, that never happens since all workers are blocked.
At that point there is no way to get out of that stale-mate. You have a dead-lock. Now this is usually not a problem, since most calls will eventually return. However since flock depends on a resource becoming available that cannot ever become available any more, flock is problematic in this context.
The solutions could be:
Thoughts?
The solution is to avoid blocking libuv
loop. Which means use exnb
flag instead of ex
like I did here.
Once I found the root cause, I was aware of that solution. Thanks for noting it down for posterity. I think this issue can only be fixed by documentation. FS-Ext is giving you a mighty big gun to shoot yourself in the foot.
I can already envision an app using 3 different libraries that use blocking locks. And then sometimes, when the timing is just right, the app suddenly stops working.
I guess that just means a heightened need to code-audit any module that has fs-ext in its dependency tree. :)
When calling flock to lock a single file exclusively but having distinct fd's more than 4 time only the first lock succeeds.
Test Code:
this works if count is 4 or less, but once count hits 5 it stops working:
Output for count=4:
Output for count=5:
after which it hangs, because there are open files, but the second lock is never acquired.
Just wanted to note this bug for now, I'll try to look into what's happening on the C++ level when I have some more time.