Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Copying then pasting text directly into node REPL freezes it - Windows #32999

Closed
powershellwhizz opened this issue Apr 22, 2020 · 10 comments
Closed
Labels
confirmed-bug Issues with confirmed bugs. windows Issues and PRs related to the Windows platform.

Comments

@powershellwhizz
Copy link

powershellwhizz commented Apr 22, 2020

As subject says. It only happens with large amounts of text, maybe something in relation to the buffer size?

node version v12.16.2
64 bit Windows 10

  • Subsystem: none

What steps will reproduce the bug?

Open CMD, type "node" press enter to get the node repl. Now copy the below code, then right click in the node console to paste text. It will only paste the first line of code and freeze up node. It becomes completely unresponsive.

How often does it reproduce? Is there a required condition?

Everytime when the copied code seems to be over a certain size. Don't know what that size is but happens no matter what the code is. The sample code provided will replicate the issue.

What is the expected behavior?

All text is pasted and executed line by line like other copy and paste operations.

What do you see instead?

Node locks up after the first line of the copied text

Additional information

Sample code below. Here is a quick vid of node locking up as described above. https://streamable.com/ep7wqt The cursor just flashes but it is unresponsive to key strokes and doesn't do anything else.
NOTE; the code has been changed to take out the IP so IF does execute it will error as I just replaced some keywords with random text. Ignore this, the point of it is to show that it won't copy and paste past the first line, it will freeze.

//{"_id":"56aba3108d6d183da42403c2"}
//placeholder
const request = require('request');
var mongoose = require ("mongoose");
var lodash = require ("lodash");
var myFuncs = require("./functions");



var item_urls;
var options = {
    json: true
  };

var test = [] ;
function updateDB (){
    var url = "get stuff";


    request(url, options, (error, res, body) =>{
        if (error) {
            return console.log(error)
          };

          if (!error && res.statusCode == 200) {
            console.log("executing cb1");
            item_urls = body.payload.items;
            myFuncs.fixItemIDs (item_urls);
            var primes = item_urls.filter(item => item.item_name.includes("Strun Wraith Set")); 
            for (item in primes) 
            {
                let url = `https://get more stuff/v1/items/${primes[item].url_name}`;
               // console.log (url);
                request(url, options, (error, res, body) =>{
                    if (error) {
                        return console.log(error)
                      };

                      if (!error && res.statusCode == 200) {

                          console.log(`Getting item ${url}`);
                          test.push(body.payload.item);
                          myFuncs.fixItemIDs (test);
                      }
                    });

            };  
            console.log ("done");          


          };
    });
}

updateDB();
@bzoz
Copy link
Contributor

bzoz commented Apr 22, 2020

Hm, it did not reproduce at first, but now it does indeed freeze.

@bzoz bzoz added confirmed-bug Issues with confirmed bugs. windows Issues and PRs related to the Windows platform. labels Apr 22, 2020
@powershellwhizz
Copy link
Author

I think I know what you did to get it work the first time. For some reason, if you open the node REPL fresh, then type ANYTHING and hit enter, you can now copy and paste the entire text. It seems to be something related to copying pasting the first line of a lot of code. Try that. As long you manually type something (anything) on the first line of the REPL and it enter you will then be able to copy and paste the code without issue

@bzoz
Copy link
Contributor

bzoz commented Apr 22, 2020

It looks like it does not matter what you paste, I was able to reproduce this by just using 1000x letter a, each on a new line. The content of .node_repl_history also does affect this.

It also reproduces on v14 and v10, to does not look like it reproduces on Linux.

@bzoz
Copy link
Contributor

bzoz commented Apr 22, 2020

It deadlocks in libuv on

uv_sem_wait(&uv_tty_output_lock);

when trying to restore tty raw mode after running the code.

@powershellwhizz
Copy link
Author

So it's triggered by line numbers? What do you think it is? HOw did you trace that btw? I was trying to figure that out myself, I'm new to node and guess you used some debug tool?

@bzoz
Copy link
Contributor

bzoz commented Apr 23, 2020

No, it looks like a race condition deep inside the C layers that handle the console, it is not related to the content you are pasting.

The console can run in two modes: line and raw. REPL is using the raw mode, which allows for greater control, but in this mode, we don't get Ctrl+C interrupts. So to allow users to interrupt a script that is running too long we switch back to line mode before evaluating the script.

On Windows this is complicated, we first need to interrupt the current console read. We do that by sending a fake Enter key and catching it later inside the read handler. All this happens in libuv, the C part of Node that communicates with the OS. Down there, we are using threads, and so we are also using various locks, and so we get multithreading bugs from time to time. Like this one - since it only reproduces from time to time, I guess there is a race there somewhere.

As for debugging Node:

  • The code of the modules is here. You can just copy the interesting file (it would be repl.js here), modify it and walk through it with a debugger. Using --expose-internals Node flag will make those require('internal/...') calls work.
  • By using --inspect-brk-node will set a breakpoint inside the Node.js bootstrapping JS code.
  • There are debug(...) things inside the codebase, like here. You can make them print stuff by setting the NODE_DEBUG environment variable. Set it to the name of the module you want to debug (or a list of modules, separated by a comma) and those debug calls will produce output. Some more info is here.
  • console.log usually helps a lot :)
  • at some point, the Node.js code will use a thing called binding, like here. Those are places where JS code calls into C++. If you - for example - have binding.access you can grep the codebase for "access" string. You then look for a place like this. Now it is easy to find the Access method, it is in the same file. Now you can set breakpoints in Visual Studio, or add a printf here and there.
  • The various uv_* functions are from libuv. If something works on one platform and crashes on another, this is usually the place where the problem is. Node keeps its copy of libuv here. You can add breakpoints and printfs here too. Since its C, even release builds work well with the debugger.

@powershellwhizz
Copy link
Author

That is a very detailed response. thanks for taking the time to write it

lander0s pushed a commit to lander0s/libuv that referenced this issue Jun 11, 2020
The variable uv__read_console_status is left as IN_PROGRESS when the
operation was cancelled by the main thread requesting a trap
(race condition?).

This confuses the next call to uv__cancel_read_console(...) therefore
causing a deadlock due to a semaphore aquisition on the main thread that
is never released by the reading thread.

Fixes: nodejs/node#32999
lander0s added a commit to lander0s/libuv that referenced this issue Jun 11, 2020
The variable uv__read_console_status is left as IN_PROGRESS when the
operation is cancelled ahead of time by the main thread requesting a
trap (race condition?).

This confuses the next call to uv__cancel_read_console(...) causing
a deadlock due to a semaphore aquisition that is never released by
the reading thread.

Setting the status variable back to COMPLETE or NOT_STARTED fixes
the issue.

Fixes: nodejs/node#32999
@lander0s
Copy link

lander0s commented Jun 11, 2020

I think I found a solution.

apparently the race condition strikes here leaving the variable uv__read_console_status in an inconsistent state (IN_PROGRESS)

IN_PROGRESS means being blocked at ReadConsoleW but in this case the thread has returned 0, this confuses the next call to uv__cancel_read_console(...) which aquires this semaphore expecting the reading thread to release it here

you can demostrate this by adding a Sleep(200); before this line which mitigates the race condition letting the reading thread to arrive first at ReadConsoleW therefore the bug does not occurs.

of course, the solution is not the sleep instruction, but setting the status variable to COMPLETE or NOT_STARTED in that case

@powershellwhizz
Copy link
Author

So forgive me for being a noob but I am new to tracking and fixing bug via GitHib - I see landers found and fixed it and raised a commit. So I guess someone will accept that and it will be merged into the main branch? When that happens does this ticket get closed somehow and marked as resolved/fixed? And finally, how does it get pushed into the next (I assume next) version of Node? How can I track it has made it's way into a certain build so I can download and test myself?

Thanks guys!

bzoz pushed a commit to libuv/libuv that referenced this issue Jun 15, 2020
The variable uv__read_console_status is left as IN_PROGRESS when the
operation is canceled ahead of time by the main thread requesting a
trap (race condition?).

This confuses the next call to uv__cancel_read_console(...) causing
a deadlock due to a semaphore acquisition that is never released by
the reading thread.

Setting the status variable back to COMPLETE or NOT_STARTED fixes
the issue.

Ref: nodejs/node#32999

PR-URL: #2882
Reviewed-By: Bartosz Sosnowski <bartosz@janeasystems.com>
@bzoz
Copy link
Contributor

bzoz commented Jul 13, 2020

Libuv was updated: #34187, it includes the fix for this issue.

@bzoz bzoz closed this as completed Jul 13, 2020
musm pushed a commit to musm/libuv that referenced this issue Jul 23, 2020
The variable uv__read_console_status is left as IN_PROGRESS when the
operation is canceled ahead of time by the main thread requesting a
trap (race condition?).

This confuses the next call to uv__cancel_read_console(...) causing
a deadlock due to a semaphore acquisition that is never released by
the reading thread.

Setting the status variable back to COMPLETE or NOT_STARTED fixes
the issue.

Ref: nodejs/node#32999

PR-URL: libuv#2882
Reviewed-By: Bartosz Sosnowski <bartosz@janeasystems.com>
(cherry picked from commit aeab873)
musm pushed a commit to musm/libuv that referenced this issue Jul 23, 2020
The variable uv__read_console_status is left as IN_PROGRESS when the
operation is canceled ahead of time by the main thread requesting a
trap (race condition?).

This confuses the next call to uv__cancel_read_console(...) causing
a deadlock due to a semaphore acquisition that is never released by
the reading thread.

Setting the status variable back to COMPLETE or NOT_STARTED fixes
the issue.

Ref: nodejs/node#32999

PR-URL: libuv#2882
Reviewed-By: Bartosz Sosnowski <bartosz@janeasystems.com>
(cherry picked from commit aeab873)
JeffroMF pushed a commit to JeffroMF/libuv that referenced this issue May 16, 2022
The variable uv__read_console_status is left as IN_PROGRESS when the
operation is canceled ahead of time by the main thread requesting a
trap (race condition?).

This confuses the next call to uv__cancel_read_console(...) causing
a deadlock due to a semaphore acquisition that is never released by
the reading thread.

Setting the status variable back to COMPLETE or NOT_STARTED fixes
the issue.

Ref: nodejs/node#32999

PR-URL: libuv#2882
Reviewed-By: Bartosz Sosnowski <bartosz@janeasystems.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
confirmed-bug Issues with confirmed bugs. windows Issues and PRs related to the Windows platform.
Projects
None yet
Development

No branches or pull requests

3 participants