Pkg: Unable to use baked runtime options in forked scripts

Created on 29 Jun 2018  路  3Comments  路  Source: vercel/pkg

The problem:

If you write a simple script that forks, and set max_old_space_size, pkg will fail with:

Error: Cannot find module '--max_old_space_size=4096'

This works fine when running directly from node (node --max-old-space-size=4092 index.js). It is related to #334. If you comment out the fork line, pkg will successfully set the parameter for index.js, but of course then forking is disabled.

Steps to reproduce:

index.js:

const v8 = require('v8');
const path = require('path');
const { fork } = require('child_process');
fork(path.join(__dirname, 'forked.js'));
// if you compile without --options max_old_space_size, this will also fail with the same error:
//fork(path.join(__dirname, 'forked.js'), [], {
//    execArgv: ['--max_old_space_size=4092'],
//});
console.log('parent execArgv', process.execArgv);
console.log('parent heap', v8.getHeapStatistics());

forked.js:

const v8 = require('v8');
console.log('forked execArgv', process.execArgv);
console.log('forked heap', v8.getHeapStatistics());

package.json:

{
  "name": "fork",
  "bin": "index.js",
  "pkg": {
    "targets": [
      "node10"
    ]
  }
}

Compiled and run like this:
pkg --options max_old_space_size=4096 . && ./fork

...using [email protected] installed using node 10.4.1.

Most helpful comment

I had a look at this today and was able to fix the problem. All the tests run and my problem is fixed anyway. I started writing a test for it, but I couldn't finish it on time. It _almost_ works :)

Anyway, this branch should make it possible

All 3 comments

I am also facing the same issue. In my case I am using fork via cluster module.

test.js

const cluster = require('cluster');
if (cluster.isMaster) {
    console.log(`Versions: ${JSON.stringify(process.versions)}`);
    cluster.fork();
} else {
    console.log(`${cluster.worker.id}: Executing Code`);
    setTimeout(() => {
        console.log(`${cluster.worker.id}: Exiting.`);
        process.exit()
    }, 2000);
}

Compiling with:

pkg --options max_old_space_size=4096 -t win-x64 test.js

Exits with following:

Versions: {"http_parser":"2.8.0","node":"8.11.3","v8":"6.2.414.54","uv":"1.19.1","zlib":"1.2.11","ares":"1.10.1-DEV","modules":"57","nghttp2":"1.32.0","napi":"3","openssl":"1.0.2o","icu":"60.1","unicode":"10.0","cldr":"32.0","tz":"2017c","pkg":"4.3.3"}
module.js:547
    throw err;
    ^

Error: Cannot find module '--max_old_space_size=4096'
    at Function.Module._resolveFilename (module.js:545:15)
    at Function.Module._resolveFilename (pkg/prelude/bootstrap.js:1278:46)
    at Function.Module._load (module.js:472:25)
    at Function.Module.runMain (pkg/prelude/bootstrap.js:1307:12)
    at startup (bootstrap_node.js:227:16)
    at bootstrap_node.js:648:3

As can be seen from the output, the system is using node version 8.11.3 and pkg 4.3.3.
I tried with [email protected], with:

pkg --options max_old_space_size=4096 -t latest-win-x64 test.js

Results in:

Versions: {"http_parser":"2.7.0","node":"8.6.0","v8":"6.0.287.53","uv":"1.14.1","zlib":"1.2.11","ares":"1.10.1-DEV","modules":"57","nghttp2":"1.25.0","openssl":"1.0.2l","icu":"59.1","unicode":"9.0","cldr":"31.0.1","tz":"2017b","pkg":"4.2.6"}
1: Executing Code
1: Exiting.

So this does seem to work. I think the bug is present on pkg 4.3 onwards.

I had a look at this today and was able to fix the problem. All the tests run and my problem is fixed anyway. I started writing a test for it, but I couldn't finish it on time. It _almost_ works :)

Anyway, this branch should make it possible

@bergheim 's branch did not work completely for me, however I discovered that if I simply manually forced the value of execArgv to be an empty array when setting up a Cluster or forking a ChildProcess, then this issue is avoided, while still inheriting the execArgv from the base process.

                Cluster.setupMaster({
                    exec: workerPath,
                    execArgv: []
                });
                ChildProcess.fork(
                    workerPath,
                    [], 
                    {
                        execArgv: []
                    }
                );

This leads me to suspect that somehow execArgv is being either applied twice or the original is not being fully removed at these points, leading to internal confusion when the system attempts to re-parse the worker address and execArgv.

I have verified that this works for me by running a load that would normally crash with max_old_space_size < 8019.

Also, it would be good if we could explicitly show in the Options section of the homepage that to include more than 1 option, they must be separated by hugging commas:

pkg app.js --options expose-gc
pkg app.js --options expose-gc,max_old_space_size=4096
Was this page helpful?
0 / 5 - 0 ratings

Related issues

gpip picture gpip  路  3Comments

j-brown picture j-brown  路  4Comments

jflayhart picture jflayhart  路  4Comments

Nisthar picture Nisthar  路  4Comments

erikd picture erikd  路  3Comments