6

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.

Aurora0001
  • 10,827
  • 5
  • 47
  • 50
gfrung4
  • 1,288
  • 2
  • 12
  • 19
  • 2
    The error is pointing to [this line](https://github.com/nodejs/node/blob/master/lib/net.js#L10) being the culprit. I'm still digging to see *why* that is (also, could you find out your Node version [like this](http://stackoverflow.com/a/29164012/6650102)?) – Aurora0001 Nov 25 '16 at 20:08
  • 2
    @Aurora0001 When I launch Node-Webkit as described in that link, there is no "address bar" to type into. I do, however, see the version listed in the lower right corner. It looks like this: https://dl.dropboxusercontent.com/u/8521871/hosted/stackexchange/nodewebkitversion.png – gfrung4 Nov 25 '16 at 20:13
  • 2
    That's just as helpful - thanks! It might be worth trying an older version of NW.js if you haven't already; my suspicion is that `cares_wrap` isn't installed correctly but I have *no clue* why this doesn't work without an internet connection yet. – Aurora0001 Nov 25 '16 at 20:16
  • 2
    If it helps, I just got the version I'm using from the homepage ( https://nwjs.io/ ). I clicked the blue "SDK" button (one on the right). I'll see if an older one works. – gfrung4 Nov 25 '16 at 20:18
  • 1
    I've just tried to reproduce with no luck. It might be worth redownloading 0.18.8 and seeing if the download was corrupt somehow. Also, what versions of Node and Chromium are used in 0.18.0? – Aurora0001 Nov 25 '16 at 20:27
  • 2
    @Aurora0001 Node v6.8.0 and Chromium 54.0.2840.59 are in nw.js v0.18.0. – gfrung4 Nov 25 '16 at 20:31
  • 2
    Oops. Realized I had been commenting here all along, and I couldn't do that very well without Internet. I had my Internet on the whole time. No, it does NOT work in v0.18.0 without Internet. I mistakenly left Internet on, and it works with Internet always. – gfrung4 Nov 25 '16 at 20:36
  • 1
    Right. Which OS are you on? I couldn't reproduce the behaviour with Ubuntu 16.10. Also, it might be worth trying even older versions than 0.18 just in case it fixes the problem. By the way, just found a potential similar issue: [npm --version throws an error on Windows 7](http://stackoverflow.com/questions/40593586/npm-version-throws-an-error-on-windows-7). – Aurora0001 Nov 25 '16 at 20:38
  • 1
    Please put the 24 line example into your question pasted as text. I learned a long time ago not to download and unzip foreign untrusted zip files like you linked to. I will, however, look at your code if it's pasted into your question and formatted properly as per the stackoverflow guidelines. – jfriend00 Nov 25 '16 at 20:47
  • It looks like this is an issue almost exclusively for Windows 10 systems (see [#5588](https://github.com/nodejs/node/issues/5588)). [#8966](https://github.com/nodejs/node/issues/8966) also seems relevant. I *think* this only happens when the DNS is in a bad state, and [Electron #6437](https://github.com/electron/electron/issues/6437) seems to have some reproduction hints. – Aurora0001 Nov 25 '16 at 20:51
  • 1
    @jfriend00 I have added my example to the question, as well as my operating system. Both of those should have been there from the start, and I apologize for that. I have removed my zip link for security reasons. I know it's not malicious, but I would have trouble trusting a random Dropbox zip on the Internet too! – gfrung4 Nov 25 '16 at 20:52
  • @user1465113 does the [LTS](http://nwjs.io/downloads/) work? – Aurora0001 Nov 25 '16 at 20:56
  • @Aurora0001 Actually, in the LTS it's worse. My example runs with Internet just fine, but without Internet it crashes instantly. The window pops up and disappears before I can do anything. I used `setTimeout` around my code to give myself a few seconds to press `F12` and open the console. Once the code runs, I see the `Check 1` flash for an instant before it crashes. – gfrung4 Nov 25 '16 at 21:09

1 Answers1

4

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.

Aurora0001
  • 10,827
  • 5
  • 47
  • 50
  • 1
    It seems `net` is used for IPC in `child_process.fork()`. The documentation says that "The returned ChildProcess will have an additional communication channel built-in that allows messages to be passed back and forth between the parent and child." I never use this, and it's disappointing that it breaks what I am using. However, it's marked as "stable" so I don't think they'll be removing it. Would it be possible for me to remove `fork()` and the `net` requirement myself, making my own `child_process` module? Since `child_process` is built-in, I don't even know where I'd begin. – gfrung4 Nov 26 '16 at 19:28
  • I don't know whether you'd be able to do this without recompiling Node and NW.js, and even if you did, I wouldn't be surprised if it broke something else which relied on `child_process.fork()`. There *might* be a way to trick c-ares into working correctly even when you're disconnected from the internet, but it'd be very hard to find out without going through the process of loading up a C debugger and running c-ares yourself. I think your best chance would be to encourage the Node team to improve the behaviour of `cares_wrap` and work around it until then, otherwise you'll risk lots of bugs. – Aurora0001 Nov 26 '16 at 19:34