Skip to content
This repository has been archived by the owner on Jan 1, 2025. It is now read-only.

Requiring a native module twice, fails #29

Closed
t-moe opened this issue Apr 4, 2016 · 5 comments
Closed

Requiring a native module twice, fails #29

t-moe opened this issue Apr 4, 2016 · 5 comments

Comments

@t-moe
Copy link

t-moe commented Apr 4, 2016

When I try to load a certain native module twice I get a strange exception.

VMError: Failed to load '<...>/deasync.node': [Module did not self-register.]

Here's a minimal example, which shows the problem. (Requires the npm module 'deasync' to run).

//Look up module path for this platform:
var path = require('path');
var fs = require('fs');

var nodeV = 'node-' + /[0-9]+\.[0-9]+/.exec(process.versions.node)[0];
var nodeVM = 'node-' + /[0-9]+/.exec(process.versions.node)[0];
var modPath = path.join(__dirname,'node_modules','deasync', 'bin', process.platform + '-' + process.arch + '-' + nodeV, 'deasync');

try{
    fs.statSync(modPath + '.node');
}
catch(ex){
    modPath = path.join(__dirname, 'node_modules','deasync','bin', process.platform + '-' + process.arch + '-' + nodeVM, 'deasync');
    fs.statSync(modPath + '.node');
}

//Beginning of the actual problem:

require(modPath); //Require native module for the first time

const NodeVM = require('vm2').NodeVM;
const vm = new NodeVM({
    require: true,
    requireExternal: true
});

vm.run("module.exports = require("+JSON.stringify(modPath)+")"); //Require module for the 2nd time, now inside vm.

//Exception occurs: VMError: Failed to load '<...>/deasync.node': [Module did not self-register.]
//Exception occurs as well if we require the same native module in two separate instances of NodeVm.
@Enteee
Copy link

Enteee commented Apr 4, 2016

an other version of the problem:

works:

const NodeVM = require('vm2').NodeVM;
const vm = new NodeVM({
    require: true,
    requireExternal: true
});

vm.run("require('deasync')", __filename);

does not work:

require('deasync');

const NodeVM = require('vm2').NodeVM;
const vm = new NodeVM({
    require: true,
    requireExternal: true
});

vm.run("require('deasync')", __filename);

Exception:

/home/ente/workspace/fluentflow/node_modules/bindings/bindings.js:85
        throw e
        ^
VMError: Module '/home/ente/workspace/fluentflow/node_modules/deasync/build/deasync.node' not found
    at _require (sandbox.js:138:17)
    at bindings (/home/ente/workspace/fluentflow/node_modules/bindings/bindings.js:78:44)
    at /home/ente/workspace/fluentflow/node_modules/deasync/index.js:24:31
    at _require (sandbox.js:190:9)
    at Object.<anonymous> (/home/ente/workspace/fluentflow/test.js:1:63)
    at NodeVM.run (/home/ente/workspace/fluentflow/node_modules/vm2/lib/main.js:393:13)
    at Object.<anonymous> (/home/ente/workspace/fluentflow/test.js:9:4)
    at Module._compile (module.js:413:34)
    at Object.Module._extensions..js (module.js:422:10)
    at Module.load (module.js:357:32)

does not work:

const NodeVM = require('vm2').NodeVM;
const vm = new NodeVM({
    require: true,
    requireExternal: true
});

vm.run("require('deasync')", __filename);

const vm2 = new NodeVM({
    require: true,
    requireExternal: true
});
vm2.run("require('deasync')", __filename);

Exception:

/home/ente/workspace/fluentflow/node_modules/bindings/bindings.js:85
        throw e
        ^
VMError: Module '/home/ente/workspace/fluentflow/node_modules/deasync/build/deasync.node' not found
    at _require (sandbox.js:138:17)
    at bindings (/home/ente/workspace/fluentflow/node_modules/bindings/bindings.js:78:44)
    at /home/ente/workspace/fluentflow/node_modules/deasync/index.js:24:31
    at _require (sandbox.js:190:9)
    at Object.<anonymous> (/home/ente/workspace/fluentflow/test.js:1:63)
    at NodeVM.run (/home/ente/workspace/fluentflow/node_modules/vm2/lib/main.js:393:13)
    at Object.<anonymous> (/home/ente/workspace/fluentflow/test.js:15:5)
    at Module._compile (module.js:413:34)
    at Object.Module._extensions..js (module.js:422:10)
    at Module.load (module.js:357:32)

@patriksimek
Copy link
Owner

Thanks for the report, both failures are cause by Module did not self-register.. Since I have almost no experience with creating native modules, any help is very welcome.

@t-moe
Copy link
Author

t-moe commented Apr 7, 2016

Ok. Here are some thoughts:

  • Module did not self register is coming from here in process.dlopen.

  • There's an interesting comment above that function:

    // FIXME(bnoordhuis) Not multi-context ready. TBD how to resolve the conflict
    // when two contexts try to load the same shared object. Maybe have a shadow
    // cache that's a plain C list or hash table that's shared across contexts?

  • I'm not familiar with the vm2 internals. Are we in a multi context scenario here?

  • If so, then this is probably linked to Make native module rerequirable. nodejs/node#5016 and we might have to ask them for help.

@patriksimek
Copy link
Owner

Yes, vm2 uses multi-context internally. This is definitely the core of the problem. It might be also somehow connected with #22 (loading a buffer in new context breaks buffer in original context).

@patriksimek
Copy link
Owner

Fixed in 3.0.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

3 participants