Repository navigation
Race condition in libuv console causes crash (assertion failure) on Windows #47715
Description
Activity
- addedc++Issues and PRs that require attention from people who are familiar with C++.Issues and PRs that require attention from people who are familiar with C++.libuvIssues and PRs related to the libuv dependency or the uv binding.Issues and PRs related to the libuv dependency or the uv binding.
on Apr 25, 2023 Is there a test with which we can reproduce this behavior?
@sivadeilra can you open an issue in https://github.com/libuv/libuv/issues ? Thanks!
Is there a test which we can reproduce this behavior?
It is a timing-related test, and the frequency that we see this is something like 1 in 100,000 processes, and that number is not an exaggeration. The repro also typically takes hours, and we only see it on large VMs that we allocate for build machines.
I have written a stress test for this, but it has not reproduced it. However, from the logic in
uv_init_console(), there is clearly a race condition around startingQueueUserWorkItem.@santigimeno , sure, I'll open an issue in libuv. Thanks.
The libuv pull request was merged. Now it's just a matter of waiting for the libuv upgrade in node so I'll go ahead and close this.
Thanks, @bnoordhuis . How long does that usually take, and how can I monitor the flow of this change? I'm not in any hurry, but I need to know when I can rebase my private hotfix onto Node.js's main trunk.
I believe @santigimeno has plans to do a new libuv release Real Soon Now(TM) and once that's done, we can upgrade libuv in node. That means it'll likely be part of the next v20.x release. Back-ports to older release branches usually take a bit longer, on the order of weeks or months.
- added a commit that references this issue
on May 24, 2023 - added 3 commits that reference this issue
on Jun 4, 2023 - added 2 commits that reference this issue
on Jul 6, 2023 - added 2 commits that reference this issue
on Jul 6, 2023 - added 6 commits that reference this issue
on Aug 14, 2023 - added a commit that references this issue
on Sep 10, 2023 - added 3 commits that reference this issue
on Sep 11, 2023
I represent a team using Node.js within Microsoft. When running Node on machines under heavy load, we have found that some Node processes fail, due to an assertion failing within
/deps/uv/win/tty.c. This is the assertion that is failing (edited for brevity):I believe the root cause is that there is a race condition in
uv_console_init():This code starts a task in a thread pool, and then queries the console size. If the thread pool task wakes up fast enough, then it will run the code that queries the console buffer size and attempts to resize it, before the first query of that console buffer succeeds, leading to the assertion failure.
Also, the worker thread can call
uv_mutex_lock(&uv__tty_console_resize_mutex);before the mutex is even initialized, which would be another source of crashes.We see this on build machines, where we spawn 140,000+ Node.js processes on machines with very large CPU counts (128 or more cores). It is more common when running VMs than when running on bare metal (where we have rarely seen this).
We are running Node.js v18.13.0. I have checked the sources, and this issue appears to be present in v18.13.0 and all later versions, up to and including main.
The fix should be to move the
QueueUserWorkItemcall after theif (GetConsoleScreenBuffer(...)) { ... }block. That should guarantee that the mutex is properly initialized, and that the first call toGetConsoleScreenBufferhas occurred, before the resizing thread can win the race.