File tree 3 files changed +32
-6
lines changed
3 files changed +32
-6
lines changed Original file line number Diff line number Diff line change @@ -276,9 +276,16 @@ Environment::~Environment() {
276
276
TRACE_EVENT_NESTABLE_ASYNC_END0 (
277
277
TRACING_CATEGORY_NODE1 (environment), " Environment" , this );
278
278
279
- // Dereference all addons that were loaded into this environment.
280
- for (binding::DLib& addon : loaded_addons_) {
281
- addon.Close ();
279
+ // Do not unload addons on the main thread. Some addons need to retain memory
280
+ // beyond the Environment's lifetime, and unloading them early would break
281
+ // them; with Worker threads, we have the opportunity to be stricter.
282
+ // Also, since the main thread usually stops just before the process exits,
283
+ // this is far less relevant here.
284
+ if (!is_main_thread ()) {
285
+ // Dereference all addons that were loaded into this environment.
286
+ for (binding::DLib& addon : loaded_addons_) {
287
+ addon.Close ();
288
+ }
282
289
}
283
290
}
284
291
Original file line number Diff line number Diff line change 3
3
#include < stdio.h>
4
4
#include < stdlib.h>
5
5
#include < v8.h>
6
+ #include < uv.h>
6
7
7
8
using v8::Context;
8
9
using v8::HandleScope;
@@ -41,6 +42,17 @@ void Initialize(Local<Object> exports,
41
42
const_cast <void *>(static_cast <const void *>(" cleanup" )));
42
43
node::AddEnvironmentCleanupHook (context->GetIsolate (), Dummy, nullptr );
43
44
node::RemoveEnvironmentCleanupHook (context->GetIsolate (), Dummy, nullptr );
45
+
46
+ if (getenv (" addExtraItemToEventLoop" ) != nullptr ) {
47
+ // Add an item to the event loop that we do not clean up in order to make
48
+ // sure that for the main thread, this addon's memory persists even after
49
+ // the Environment instance has been destroyed.
50
+ static uv_async_t extra_async;
51
+ uv_loop_t * loop = node::GetCurrentEventLoop (context->GetIsolate ());
52
+ int err = uv_async_init (loop, &extra_async, [](uv_async_t *) {});
53
+ assert (err == 0 );
54
+ uv_unref (reinterpret_cast <uv_handle_t *>(&extra_async));
55
+ }
44
56
}
45
57
46
58
NODE_MODULE_CONTEXT_AWARE (NODE_GYP_MODULE_NAME, Initialize)
Original file line number Diff line number Diff line change @@ -6,12 +6,19 @@ const path = require('path');
6
6
const { Worker } = require ( 'worker_threads' ) ;
7
7
const binding = path . resolve ( __dirname , `./build/${ common . buildType } /binding` ) ;
8
8
9
- if ( process . argv [ 2 ] === 'child ' ) {
9
+ if ( process . argv [ 2 ] === 'worker ' ) {
10
10
new Worker ( `require(${ JSON . stringify ( binding ) } );` , { eval : true } ) ;
11
- } else {
11
+ return ;
12
+ } else if ( process . argv [ 2 ] === 'main-thread' ) {
13
+ process . env . addExtraItemToEventLoop = 'yes' ;
14
+ require ( binding ) ;
15
+ return ;
16
+ }
17
+
18
+ for ( const test of [ 'worker' , 'main-thread' ] ) {
12
19
const proc = child_process . spawnSync ( process . execPath , [
13
20
__filename ,
14
- 'child'
21
+ test
15
22
] ) ;
16
23
assert . strictEqual ( proc . stderr . toString ( ) , '' ) ;
17
24
assert . strictEqual ( proc . stdout . toString ( ) , 'ctor cleanup dtor' ) ;
You can’t perform that action at this time.
0 commit comments