test,doc: add tests and docs for addon unloading
Originally from portions of https://github.com/nodejs/node/pull/23319/. PR-URL: https://github.com/nodejs/node/pull/24861 Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: Joyee Cheung <joyeec9h3@gmail.com>
This commit is contained in:
parent
bf36f0755c
commit
622e348d8f
@ -234,6 +234,23 @@ NODE_MODULE_INIT(/* exports, module, context */) {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
#### Worker support
|
||||||
|
|
||||||
|
In order to support [`Worker`][] threads, addons need to clean up any resources
|
||||||
|
they may have allocated when such a thread exists. This can be achieved through
|
||||||
|
the usage of the `AddEnvironmentCleanupHook()` function:
|
||||||
|
|
||||||
|
```c++
|
||||||
|
void AddEnvironmentCleanupHook(v8::Isolate* isolate,
|
||||||
|
void (*fun)(void* arg),
|
||||||
|
void* arg);
|
||||||
|
```
|
||||||
|
|
||||||
|
This function adds a hook that will run before a given Node.js instance shuts
|
||||||
|
down. If necessary, such hooks can be removed using
|
||||||
|
`RemoveEnvironmentCleanupHook()` before they are run, which has the same
|
||||||
|
signature.
|
||||||
|
|
||||||
### Building
|
### Building
|
||||||
|
|
||||||
Once the source code has been written, it must be compiled into the binary
|
Once the source code has been written, it must be compiled into the binary
|
||||||
@ -1349,6 +1366,7 @@ Test in JavaScript by running:
|
|||||||
require('./build/Release/addon');
|
require('./build/Release/addon');
|
||||||
```
|
```
|
||||||
|
|
||||||
|
[`Worker`]: worker_threads.html#worker_threads_class_worker
|
||||||
[Electron]: https://electronjs.org/
|
[Electron]: https://electronjs.org/
|
||||||
[Embedder's Guide]: https://github.com/v8/v8/wiki/Embedder's%20Guide
|
[Embedder's Guide]: https://github.com/v8/v8/wiki/Embedder's%20Guide
|
||||||
[Linking to Node.js' own dependencies]: #addons_linking_to_node_js_own_dependencies
|
[Linking to Node.js' own dependencies]: #addons_linking_to_node_js_own_dependencies
|
||||||
|
14
test/addons/hello-world/test-worker.js
Normal file
14
test/addons/hello-world/test-worker.js
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
// Flags: --experimental-worker
|
||||||
|
'use strict';
|
||||||
|
const common = require('../../common');
|
||||||
|
const assert = require('assert');
|
||||||
|
const path = require('path');
|
||||||
|
const { Worker } = require('worker_threads');
|
||||||
|
const binding = path.resolve(__dirname, `./build/${common.buildType}/binding`);
|
||||||
|
|
||||||
|
const w = new Worker(`
|
||||||
|
require('worker_threads').parentPort.postMessage(
|
||||||
|
require(${JSON.stringify(binding)}).hello());`, { eval: true });
|
||||||
|
w.on('message', common.mustCall((message) => {
|
||||||
|
assert.strictEqual(message, 'world');
|
||||||
|
}));
|
46
test/addons/worker-addon/binding.cc
Normal file
46
test/addons/worker-addon/binding.cc
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
#include <assert.h>
|
||||||
|
#include <node.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <v8.h>
|
||||||
|
|
||||||
|
using v8::Context;
|
||||||
|
using v8::HandleScope;
|
||||||
|
using v8::Isolate;
|
||||||
|
using v8::Local;
|
||||||
|
using v8::Object;
|
||||||
|
using v8::Value;
|
||||||
|
|
||||||
|
size_t count = 0;
|
||||||
|
|
||||||
|
struct statically_allocated {
|
||||||
|
statically_allocated() {
|
||||||
|
assert(count == 0);
|
||||||
|
printf("ctor ");
|
||||||
|
}
|
||||||
|
~statically_allocated() {
|
||||||
|
assert(count == 0);
|
||||||
|
printf("dtor");
|
||||||
|
}
|
||||||
|
} var;
|
||||||
|
|
||||||
|
void Dummy(void*) {
|
||||||
|
assert(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Cleanup(void* str) {
|
||||||
|
printf("%s ", static_cast<const char*>(str));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Initialize(Local<Object> exports,
|
||||||
|
Local<Value> module,
|
||||||
|
Local<Context> context) {
|
||||||
|
node::AddEnvironmentCleanupHook(
|
||||||
|
context->GetIsolate(),
|
||||||
|
Cleanup,
|
||||||
|
const_cast<void*>(static_cast<const void*>("cleanup")));
|
||||||
|
node::AddEnvironmentCleanupHook(context->GetIsolate(), Dummy, nullptr);
|
||||||
|
node::RemoveEnvironmentCleanupHook(context->GetIsolate(), Dummy, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
NODE_MODULE_CONTEXT_AWARE(NODE_GYP_MODULE_NAME, Initialize)
|
9
test/addons/worker-addon/binding.gyp
Normal file
9
test/addons/worker-addon/binding.gyp
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
'targets': [
|
||||||
|
{
|
||||||
|
'target_name': 'binding',
|
||||||
|
'defines': [ 'V8_DEPRECATION_WARNINGS=1' ],
|
||||||
|
'sources': [ 'binding.cc' ]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
21
test/addons/worker-addon/test.js
Normal file
21
test/addons/worker-addon/test.js
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
// Flags: --experimental-worker
|
||||||
|
'use strict';
|
||||||
|
const common = require('../../common');
|
||||||
|
const assert = require('assert');
|
||||||
|
const child_process = require('child_process');
|
||||||
|
const path = require('path');
|
||||||
|
const { Worker } = require('worker_threads');
|
||||||
|
const binding = path.resolve(__dirname, `./build/${common.buildType}/binding`);
|
||||||
|
|
||||||
|
if (process.argv[2] === 'child') {
|
||||||
|
new Worker(`require(${JSON.stringify(binding)});`, { eval: true });
|
||||||
|
} else {
|
||||||
|
const proc = child_process.spawnSync(process.execPath, [
|
||||||
|
'--experimental-worker',
|
||||||
|
__filename,
|
||||||
|
'child'
|
||||||
|
]);
|
||||||
|
assert.strictEqual(proc.stderr.toString(), '');
|
||||||
|
assert.strictEqual(proc.stdout.toString(), 'ctor cleanup dtor');
|
||||||
|
assert.strictEqual(proc.status, 0);
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user