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
|
||||
|
||||
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');
|
||||
```
|
||||
|
||||
[`Worker`]: worker_threads.html#worker_threads_class_worker
|
||||
[Electron]: https://electronjs.org/
|
||||
[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
|
||||
|
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