Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does require('child-process') not work in Node Webkit without an Internet connection?

In a Node-Webkit application running on the latest stable release (v0.18.8), I have these three lines:

console.log("Check 1");
var spawn = require('child_process').spawn;
console.log("Check 2");

When I have Internet, I get the expected output:

Check 1
Check 2

When I disconnect from the Internet, or there is no network available, I get:

Check 1
net.js:10 Uncaught Error: EFILE
    at net.js:10:23
    at NativeModule.compile (bootstrap_node.js:531:7)
    at NativeModule.require (bootstrap_node.js:472:18)
    at internal/child_process.js:6:13
    at NativeModule.compile (bootstrap_node.js:531:7)
    at NativeModule.require (bootstrap_node.js:472:18)
    at child_process.js:12:23
    at NativeModule.compile (bootstrap_node.js:531:7)
    at Function.NativeModule.require (bootstrap_node.js:472:18)
    at Function.Module._load (module.js:446:25)

The console.log("Check 2") is never run, and the rest of the script is ignored.

I shouldn't need an Internet connection to require something, so I'm confused as to what's going wrong here. This error also happens with some other require() statements, but not all. For example, require('nw.gui') works fine.

How can I use require() without an Internet connection?

I'm running Windows 10, 64-bit.


Here's an example demonstrating the issue:

index.html

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html lang="en">

<head>
    <meta http-equiv="content-type" content="text/html; charset=utf-8">
    <title>Title</title>
</head>

<body>
    <p>Body</p>
</body>

<script type="text/javascript">
    console.log("Check 1");
    var spawn = require('child_process').spawn;
    console.log("Check 2");
</script>

</html>

package.json

{
    "name": "Demo",
    "version": "1.0.0",
    "main": "index.html"
}

Place these two files in a folder and run with Node-Webkit with Internet and without. Press F12 to open the developer tools. There should be no error when run with Internet, and an error when run without.

like image 634
gfrung4 Avatar asked Nov 25 '16 19:11

gfrung4


People also ask

How does child process work in node JS?

Usually, Node. js allows single-threaded, non-blocking performance but running a single thread in a CPU cannot handle increasing workload hence the child_process module can be used to spawn child processes. The child processes communicate with each other using a built-in messaging system.

Can we create child processes in node applications?

Node provides child_process module which provides ways to create child process.


1 Answers

It looks like you're a victim of a bug in the c-ares library (and its Node wrapper) which affects some Windows 10 systems when the DNS configuration isn't valid (e.g. if you aren't connected to the network).

Why does this affect child_process?

The child_process module requires internal/child_process, which is the standard library's wrapper around the C++ API that Node provides. Rather bizarrely, internal/child_process requires net, the network module, which then loads cares_wrap, the wrapper around c-ares which Node uses for DNS resolution.

For some reason, internal/child_process has some helper code for net, so the net module has to be loaded and all its dependencies (including cares_wrap) must be loaded, meaning that if your DNS configuration is broken, child_process can't load its dependency, internal/child_process.

Since you get an EFILE, that suggests that this part of c-ares fails:

if (get_DNS_Windows(&line))
{
    status = config_nameserver(&servers, &nservers, line);
    ares_free(line);
} 

if (status == ARES_SUCCESS)
  status = ARES_EOF;
else
  /* Catch the case when all the above checks fail (which happens when there
     is no network card or the cable is unplugged) */
  status = ARES_EFILE;

Without a C debugger, it'd be very hard to pinpoint the exact problem, but my guess is that get_DNS_Windows() fails in some way.

How can this issue be resolved?

This is the far more unsatisfactory part of my answer. When using the LTS of NW.js, it looks like you get this issue, since older versions of Node simply crashed if the c-ares initialisation failed. This was changed in this commit, so errors are now caught and thrown as a JS exception instead. Therefore, I believe the behaviour will have changed after Node v6.7.0.

As far as I can tell, the best solution is to just run Node in a virtual machine (or perhaps a Docker/Vagrant container) to work around the issue until it's fixed upstream. It would definitely be worth reporting the issue to either Node or c-ares with as much information as you can (this post may be helpful to someone, provided I've not made any mistakes). I would also watch #8966 since it seems to be very similar if not the same as your issue.

like image 195
Aurora0001 Avatar answered Oct 02 '22 16:10

Aurora0001