From 5f223759229a112af41508c470d683152523c6e3 Mon Sep 17 00:00:00 2001 From: Ezequiel Garcia Date: Sat, 29 Apr 2017 16:06:22 -0400 Subject: [PATCH] src: add support to pass flags to dlopen * add constants for dlopen flags, which are needed for dlopen's flag passing. * introduce an optional parameter for process.dlopen(), allowing to pass dlopen flags (using values from os.constants.dlopen). If no flags are passed, the default behavior is to load the library with RTLD_LAZY (perform lazy binding) and RTLD_LOCAL (symbols are available only locally). PR-URL: https://github.com/nodejs/node/pull/12794 Refs: https://github.com/nodejs/node/pull/4105 Refs: https://github.com/libuv/libuv/pull/1331 Reviewed-By: Ben Noordhuis Reviewed-By: Timothy Gu Reviewed-By: Gireesh Punathil Reviewed-By: Refael Ackermann Reviewed-By: Sakthipriyan Vairamani --- doc/api/os.md | 37 +++++++++++ doc/api/process.md | 45 +++++++++++++ lib/constants.js | 1 + src/node.cc | 81 ++++++++++++++++++++---- src/node_constants.cc | 32 ++++++++++ test/addons/dlopen-ping-pong/binding.cc | 48 ++++++++++++++ test/addons/dlopen-ping-pong/binding.gyp | 25 ++++++++ test/addons/dlopen-ping-pong/ping.c | 9 +++ test/addons/dlopen-ping-pong/test.js | 23 +++++++ test/parallel/test-binding-constants.js | 5 +- 10 files changed, 290 insertions(+), 16 deletions(-) create mode 100644 test/addons/dlopen-ping-pong/binding.cc create mode 100644 test/addons/dlopen-ping-pong/binding.gyp create mode 100644 test/addons/dlopen-ping-pong/ping.c create mode 100644 test/addons/dlopen-ping-pong/test.js diff --git a/doc/api/os.md b/doc/api/os.md index 28eff6a13f0b60..1bef5c5501688b 100644 --- a/doc/api/os.md +++ b/doc/api/os.md @@ -1170,6 +1170,43 @@ The following error codes are specific to the Windows operating system: +### dlopen Constants + +If available on the operating system, the following constants +are exported in `os.constants.dlopen`. See dlopen(3) for detailed +information. + + + + + + + + + + + + + + + + + + + + + + + + + + +
ConstantDescription
RTLD_LAZYPerform lazy binding. Node.js sets this flag by default.
RTLD_NOWResolve all undefined symbols in the library before dlopen(3) + returns.
RTLD_GLOBALSymbols defined by the library will be made available for symbol + resolution of subsequently loaded libraries.
RTLD_LOCALThe converse of RTLD_GLOBAL. This is the default behavior if neither + flag is specified.
RTLD_DEEPBINDMake a self-contained library use its own symbols in preference to + symbols from previously loaded libraries.
+ ### libuv Constants diff --git a/doc/api/process.md b/doc/api/process.md index e24bf19d9d2f44..82edcf9436c8eb 100644 --- a/doc/api/process.md +++ b/doc/api/process.md @@ -638,6 +638,48 @@ process's [`ChildProcess.disconnect()`][]. If the Node.js process was not spawned with an IPC channel, `process.disconnect()` will be `undefined`. +## process.dlopen(module, filename[, flags]) + + +* `module` {Object} +* `filename` {string} +* `flags` {os.constants.dlopen}. Defaults to `os.constants.dlopen.RTLD_LAZY`. + +The `process.dlopen()` method allows to dynamically load shared +objects. It is primarily used by `require()` to load +C++ Addons, and should not be used directly, except in special +cases. In other words, [`require()`][] should be preferred over +`process.dlopen()`, unless there are specific reasons. + +The `flags` argument is an integer that allows to specify dlopen +behavior. See the [`os.constants.dlopen`][] documentation for details. + +If there are specific reasons to use `process.dlopen()` (for instance, +to specify dlopen flags), it's often useful to use [`require.resolve()`][] +to look up the module's path. + +*Note*: An important drawback when calling `process.dlopen()` is that the +`module` instance must be passed. Functions exported by the C++ Addon will +be accessible via `module.exports`. + +The example below shows how to load a C++ Addon, named as `binding`, +that exports a `foo` function. All the symbols will be loaded before +the call returns, by passing the `RTLD_NOW` constant. In this example +the constant is assumed to be available. + +```js +const os = require('os'); +process.dlopen(module, require.resolve('binding'), + os.constants.dlopen.RTLD_NOW); +module.exports.foo(); +``` + ## process.emitWarning(warning[, options])