server.js
'use strict';
const http2 = require('http2');
const server = http2.createServer();
server.once('error', err => {
console.log(err);
});
server.on('session', session => {
console.log(session);
});
server.on('stream', (stream, headers) => {
console.log(stream, headers);
});
server.listen(12200, () => {
console.log('server start on %s', 12200);
});
client.js
'use strict';
const connect = async () => {
return new Promise(resolve => {
const client = http2.connect('http://localhost:12200', () => {
client.close();
resolve();
});
});
};
(async () => {
while (true) {
await connect();
}
})();
execute command:
node --gc-global --trace-gc --inspect server.js
node client.js
then take a snapshot in Chrome DevTools
the server process will take a core dumped.
[1] 49577 segmentation fault (core dumped) node --gc-global --trace-gc --inspect server.js
the dump file bt:
```
thread #1, stop reason = signal SIGSTOP
- frame #0: 0x00000001000a588b node`node::MemoryRetainerNode::MemoryRetainerNode(node::MemoryTracker*, node::MemoryRetainer const*) + 107
frame #1: 0x00000001000a551f node`node::MemoryTracker::AddNode(node::MemoryRetainer const*, char const*) + 87
frame #2: 0x000000010001a8e7 node`node::MemoryTracker::Track(node::MemoryRetainer const*, char const*) + 147
frame #3: 0x00000001000a450a node`node::http2::Http2Session::Http2Settings::MemoryInfo(node::MemoryTracker*) const + 134
frame #4: 0x000000010001a90b node`node::MemoryTracker::Track(node::MemoryRetainer const*, char const*) + 183
frame #5: 0x000000010003931b node`node::MemoryTracker::TrackField(char const*, node::CleanupHookCallback const&, char const*) + 193
frame #6: 0x000000010003a2ec node`void node::MemoryTracker::TrackField<std::__1::unordered_set<node::CleanupHookCallback, node::CleanupHookCallback::Hash, node::CleanupHookCallback::Equal, std::__1::allocator<node::CleanupHookCallback> >, std::__1::__hash_const_iterator<std::__1::__hash_node<node::CleanupHookCallback, void*>*> >(char const*, std::__1::unordered_set<node::CleanupHookCallback, node::CleanupHookCallback::Hash, node::CleanupHookCallback::Equal, std::__1::allocator<node::CleanupHookCallback> > const&, char const*, char const*, bool) + 146
frame #7: 0x0000000100039598 node`node::Environment::MemoryInfo(node::MemoryTracker*) const + 524
frame #8: 0x000000010001a90b node`node::MemoryTracker::Track(node::MemoryRetainer const*, char const*) + 183
frame #9: 0x000000010003660d node`node::Environment::BuildEmbedderGraph(v8::Isolate*, v8::EmbedderGraph*, void*) + 131
frame #10: 0x000000010074f57c node`v8::internal::HeapProfiler::BuildEmbedderGraph(v8::internal::Isolate*, v8::EmbedderGraph*) + 60
frame #11: 0x00000001007589dc node`v8::internal::NativeObjectsExplorer::IterateAndExtractReferences(v8::internal::HeapSnapshotGenerator*) + 172
frame #12: 0x0000000100759396 node`v8::internal::HeapSnapshotGenerator::GenerateSnapshot() + 230
frame #13: 0x000000010074f5f1 node`v8::internal::HeapProfiler::TakeSnapshot(v8::ActivityControl*, v8::HeapProfiler::ObjectNameResolver*) + 97
frame #14: 0x0000000100940d37 node`v8_inspector::V8HeapProfilerAgentImpl::takeHeapSnapshot(v8_inspector::protocol::Maybe<bool>) + 263
frame #15: 0x00000001009ff74e node`v8_inspector::protocol::HeapProfiler::DispatcherImpl::takeHeapSnapshot(int, v8_inspector::String16 const&, v8_inspector::protocol::ProtocolMessage const&, std::__1::unique_ptr<v8_inspector::protocol::DictionaryValue, std::__1::default_delete<v8_inspector::protocol::DictionaryValue> >, v8_inspector::protocol::ErrorSupport*) + 382
frame #16: 0x00000001009fdd94 node`v8_inspector::protocol::HeapProfiler::DispatcherImpl::dispatch(int, v8_inspector::String16 const&, v8_inspector::protocol::ProtocolMessage const&, std::__1::unique_ptr<v8_inspector::protocol::DictionaryValue, std::__1::default_delete<v8_inspector::protocol::DictionaryValue> >) + 116
frame #17: 0x00000001009db538 node`v8_inspector::protocol::UberDispatcher::dispatch(int, v8_inspector::String16 const&, std::__1::unique_ptr<v8_inspector::protocol::Value, std::__1::default_delete<v8_inspector::protocol::Value> >, v8_inspector::protocol::ProtocolMessage const&) + 584
frame #18: 0x0000000100948c3a node`v8_inspector::V8InspectorSessionImpl::dispatchProtocolMessage(v8_inspector::StringView const&) + 282
frame #19: 0x0000000100107001 node`node::inspector::NodeInspectorClient::dispatchMessageFromFrontend(int, v8_inspector::StringView const&) + 239
frame #20: 0x0000000100106d52 node`node::inspector::(anonymous namespace)::SameThreadInspectorSession::Dispatch(v8_inspector::StringView const&) + 58
```
I can reproduce it on master. I used the v8 API instead of the devtools for the ease of reproducing.
'use strict';
const http2 = require('http2');
const v8 = require('v8');
const server = http2.createServer();
server.once('error', err => {
console.log(err);
});
let count = 0;
server.on('session', session => {
if (count++ % 100 === 0) {
console.log('take snapshot');
v8.writeHeapSnapshot('/tmp/snapshot.heapsnapshot');
console.log('done snapshot');
}
console.log(count++);
});
server.on('stream', (stream, headers) => {
console.log(stream, headers);
});
server.listen(12200, () => {
console.log('server start on %s', 12200);
});
See stack trace
* thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=EXC_I386_GPFLT)
frame #0: 0x0000000100030a51 node`node::MemoryRetainerNode::MemoryRetainerNode(this=0x000000010750fa90, tracker=0x00007ffeefbf5f18, retainer=<unavailable>) at memory_tracker-inl.h:29:44 [opt]
26 : retainer_(retainer) {
27 CHECK_NOT_NULL(retainer_);
28 v8::HandleScope handle_scope(tracker->isolate());
-> 29 v8::Local<v8::Object> obj = retainer_->WrappedObject();
30 if (!obj.IsEmpty()) wrapper_node_ = tracker->graph()->V8Node(obj);
31
32 name_ = retainer_->MemoryInfoName();
Target 0: (node) stopped.
(lldb) bt
* thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=EXC_I386_GPFLT)
* frame #0: 0x0000000100030a51 node`node::MemoryRetainerNode::MemoryRetainerNode(this=0x000000010750fa90, tracker=0x00007ffeefbf5f18, retainer=<unavailable>) at memory_tracker-inl.h:29:44 [opt]
frame #1: 0x00000001000306e7 node`node::MemoryTracker::AddNode(node::MemoryRetainer const*, char const*) [inlined] node::MemoryRetainerNode::MemoryRetainerNode(this=0x000000010750fa90, tracker=0x00007ffeefbf5f18, retainer=<unavailable>) at memory_tracker-inl.h:26:29 [opt]
frame #2: 0x00000001000306dc node`node::MemoryTracker::AddNode(this=0x00007ffeefbf5f18, retainer=<unavailable>, edge_name="session") at memory_tracker-inl.h:270 [opt]
frame #3: 0x00000001000305f9 node`node::MemoryTracker::Track(node::MemoryRetainer const*, char const*) [inlined] node::MemoryTracker::PushNode(this=0x00007ffeefbf5f18, retainer=<unavailable>, edge_name="session") at memory_tracker-inl.h:296:27 [opt]
frame #4: 0x00000001000305ee node`node::MemoryTracker::Track(this=0x00007ffeefbf5f18, retainer=<unavailable>, edge_name="session") at memory_tracker-inl.h:244 [opt]
frame #5: 0x00000001000ba20c node`node::http2::Http2Session::Http2Settings::MemoryInfo(node::MemoryTracker*) const [inlined] node::MemoryTracker::TrackField(this=<unavailable>, edge_name=<unavailable>, value=<unavailable>) at memory_tracker-inl.h:98:5 [opt]
frame #6: 0x00000001000ba1ae node`node::http2::Http2Session::Http2Settings::MemoryInfo(this=<unavailable>, tracker=0x00007ffeefbf5f18) const at node_http2.h:1108 [opt]
frame #7: 0x000000010003061f node`node::MemoryTracker::Track(this=0x00007ffeefbf5f18, retainer=<unavailable>, edge_name=<unavailable>) at memory_tracker-inl.h:245:13 [opt]
frame #8: 0x000000010004e24f node`node::MemoryTracker::TrackField(char const*, node::CleanupHookCallback const&, char const*) [inlined] node::MemoryTracker::TrackField(this=<unavailable>, edge_name=<unavailable>, value=<unavailable>) at memory_tracker-inl.h:98:5 [opt]
frame #9: 0x000000010004e23c node`node::MemoryTracker::TrackField(this=0x00007ffeefbf5f18, edge_name=0x0000000000000000, value=0x0000000102a14570, node_name=<unavailable>) at env.cc:937 [opt]
frame #10: 0x000000010004f44f node`void node::MemoryTracker::TrackField<std::__1::unordered_set<node::CleanupHookCallback, node::CleanupHookCallback::Hash, node::CleanupHookCallback::Equal, std::__1::allocator<node::CleanupHookCallback> >, std::__1::__hash_const_iterator<std::__1::__hash_node<node::CleanupHookCallback, void*>*> >(this=0x00007ffeefbf5f18, edge_name=<unavailable>, value=size=456, node_name=<unavailable>, element_name=<unavailable>, subtract_from_self=<unavailable>) at memory_tracker-inl.h:129:5 [opt]
frame #11: 0x000000010004e487 node`node::Environment::MemoryInfo(this=0x000000010403dc00, tracker=0x00007ffeefbf5f18) const at env.cc:981:12 [opt]
frame #12: 0x000000010003061f node`node::MemoryTracker::Track(this=0x00007ffeefbf5f18, retainer=<unavailable>, edge_name=<unavailable>) at memory_tracker-inl.h:245:13 [opt]
frame #13: 0x000000010004c672 node`node::Environment::BuildEmbedderGraph(isolate=<unavailable>, graph=<unavailable>, data=<unavailable>) at env.cc:949:11 [opt]
frame #14: 0x00000001005c12dc node`v8::internal::HeapProfiler::BuildEmbedderGraph(this=<unavailable>, isolate=<unavailable>, graph=<unavailable>) at heap-profiler.cc:60:5 [opt]
frame #15: 0x00000001005cb22c node`v8::internal::NativeObjectsExplorer::IterateAndExtractReferences(this=0x00007ffeefbf61e0, generator=<unavailable>) at heap-snapshot-generator.cc:1908:28 [opt]
frame #16: 0x00000001005cbe46 node`v8::internal::HeapSnapshotGenerator::GenerateSnapshot() [inlined] v8::internal::HeapSnapshotGenerator::FillReferences(this=<unavailable>) at heap-snapshot-generator.cc:2039:24 [opt]
frame #17: 0x00000001005cbe28 node`v8::internal::HeapSnapshotGenerator::GenerateSnapshot(this=0x00007ffeefbf60f8) at heap-snapshot-generator.cc:2002 [opt]
frame #18: 0x00000001005c1351 node`v8::internal::HeapProfiler::TakeSnapshot(this=0x0000000102a057b0, control=<unavailable>, resolver=<unavailable>) at heap-profiler.cc:70:20 [opt]
frame #19: 0x000000010005457e node`node::heap::TriggerHeapSnapshot(v8::FunctionCallbackInfo<v8::Value> const&) [inlined] node::heap::(anonymous namespace)::TakeSnapshot(isolate=<unavailable>, out=<unavailable>) at heap_utils.cc:324:35 [opt]
frame #20: 0x000000010005456d node`node::heap::TriggerHeapSnapshot(v8::FunctionCallbackInfo<v8::Value> const&) [inlined] node::heap::(anonymous namespace)::WriteSnapshot(isolate=<unavailable>, filename=<unavailable>) at heap_utils.cc:334 [opt]
frame #21: 0x0000000100054540 node`node::heap::TriggerHeapSnapshot(args=0x00007ffeefbf6740) at heap_utils.cc:376 [opt]
frame #22: 0x000000010024707c node`v8::internal::FunctionCallbackArguments::Call(this=0x00007ffeefbf67a0, handler=<unavailable>) at api-arguments-inl.h:157:3 [opt]
frame #23: 0x000000010024663d node`v8::internal::MaybeHandle<v8::internal::Object> v8::internal::(anonymous namespace)::HandleApiCallHelper<false>(isolate=0x000000010285c000, function=<unavailable>, new_target=<unavailable>, fun_data=<unavailable>, receiver=<unavailable>, args=BuiltinArguments @ 0x00007ffeefbf6840) at builtins-api.cc:109:36 [opt]
frame #24: 0x0000000100245d32 node`v8::internal::Builtin_Impl_HandleApiCall(args=<unavailable>, isolate=0x000000010285c000) at builtins-api.cc:139:5 [opt]
frame #25: 0x0000000100938359 node`Builtins_CEntry_Return1_DontSaveFPRegs_ArgvOnStack_NoBuiltinExit + 57
frame #26: 0x00000001008ad5c4 node`Builtins_InterpreterEntryTrampoline + 676
frame #27: 0x00000001008ad5c4 node`Builtins_InterpreterEntryTrampoline + 676
frame #28: 0x00000001008ad5c4 node`Builtins_InterpreterEntryTrampoline + 676
frame #29: 0x00000001008ad5c4 node`Builtins_InterpreterEntryTrampoline + 676
frame #30: 0x00000001008ad5c4 node`Builtins_InterpreterEntryTrampoline + 676
frame #31: 0x00000001008ad5c4 node`Builtins_InterpreterEntryTrampoline + 676
frame #32: 0x00000001008ad5c4 node`Builtins_InterpreterEntryTrampoline + 676
frame #33: 0x00000001008ad5c4 node`Builtins_InterpreterEntryTrampoline + 676
frame #34: 0x00000001008aaf3d node`Builtins_JSEntryTrampoline + 93
frame #35: 0x00000001008aacb8 node`Builtins_JSEntry + 120
frame #36: 0x000000010033c09e node`v8::internal::(anonymous namespace)::Invoke(v8::internal::Isolate*, v8::internal::(anonymous namespace)::InvokeParams const&) [inlined] v8::internal::GeneratedCode<unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, long, unsigned long**>::Call(this=<unavailable>, args=<unavailable>, args=<unavailable>, args=<unavailable>, args=<unavailable>, args=<unavailable>, args=<unavailable>) at simulator.h:138:12 [opt]
frame #37: 0x000000010033c09c node`v8::internal::(anonymous namespace)::Invoke(isolate=0x000000010285c000, params=0x00007ffeefbf6eb8)::InvokeParams const&) at execution.cc:266 [opt]
frame #38: 0x000000010033bddb node`v8::internal::Execution::Call(isolate=0x000000010285c000, callable=<unavailable>, receiver=<unavailable>, argc=2, argv=0x00007ffeefbf7160) at execution.cc:358:10 [opt]
frame #39: 0x00000001001dad8b node`v8::Function::Call(this=0x0000000104029218, context=<unavailable>, recv=<unavailable>, argc=2, argv=0x00007ffeefbf7160) at api.cc:4989:7 [opt]
frame #40: 0x00000001000186af node`node::InternalMakeCallback(env=<unavailable>, recv=<unavailable>, callback=<unavailable>, argc=<unavailable>, argv=0x00007ffeefbf7160, asyncContext=(async_id = 2, trigger_async_id = 1)) at callback.cc:153:21 [opt]
frame #41: 0x000000010002944b node`node::AsyncWrap::MakeCallback(this=<unavailable>, cb=(val_ = 0x0000000104029218), argc=2, argv=0x00007ffeefbf7160) at async_wrap.cc:718:27 [opt]
frame #42: 0x0000000100035d5f node`node::ConnectionWrap<node::TCPWrap, uv_tcp_s>::OnConnection(uv_stream_s*, int) [inlined] node::AsyncWrap::MakeCallback(this=0x0000000102c0c3d0, symbol=<unavailable>, argc=2) at async_wrap-inl.h:95:10 [opt]
frame #43: 0x0000000100035d28 node`node::ConnectionWrap<node::TCPWrap, uv_tcp_s>::OnConnection(uv_stream_s*, int) [inlined] node::AsyncWrap::MakeCallback(this=0x0000000102c0c3d0, symbol=<unavailable>, argc=2) at async_wrap-inl.h:71 [opt]
frame #44: 0x0000000100035d28 node`node::ConnectionWrap<node::TCPWrap, uv_tcp_s>::OnConnection(handle=<unavailable>, status=<unavailable>) at connection_wrap.cc:73 [opt]
frame #45: 0x000000010089c5de node`uv__server_io(loop=0x0000000101855630, w=0x0000000102c0c4f0, events=<unavailable>) at stream.c:570:5 [opt]
frame #46: 0x00000001008a2d60 node`uv__io_poll(loop=<unavailable>, timeout=<unavailable>) at kqueue.c:0:11 [opt]
frame #47: 0x0000000100893487 node`uv_run(loop=0x0000000101855630, mode=UV_RUN_DEFAULT) at core.c:368:5 [opt]
frame #48: 0x00000001000c1c2c node`node::NodeMainInstance::Run(this=0x00007ffeefbff3e0) at node_main_instance.cc:120:9 [opt]
frame #49: 0x000000010006cbe2 node`node::Start(argc=<unavailable>, argv=<unavailable>) at node.cc:976:38 [opt]
frame #50: 0x00007fff59d603d5 libdyld.dylib`start + 1
I also get Pure virtual function called sometimes, there may be a use-after-free for the reference from Http2Settings to Http2Session - something is holding onto the Http2Settings when its Http2Session is already gone.
See stack trace
libc++abi.dylib: Pure virtual function called!
Process 83168 stopped
* thread #1, queue = 'com.apple.main-thread', stop reason = signal SIGABRT
frame #0: 0x00007fff59e9b2c6 libsystem_kernel.dylib`__pthread_kill + 10
libsystem_kernel.dylib`__pthread_kill:
-> 0x7fff59e9b2c6 <+10>: jae 0x7fff59e9b2d0 ; <+20>
0x7fff59e9b2c8 <+12>: movq %rax, %rdi
0x7fff59e9b2cb <+15>: jmp 0x7fff59e95457 ; cerror_nocancel
0x7fff59e9b2d0 <+20>: retq
Target 0: (node) stopped.
(lldb) bt
* thread #1, queue = 'com.apple.main-thread', stop reason = signal SIGABRT
* frame #0: 0x00007fff59e9b2c6 libsystem_kernel.dylib`__pthread_kill + 10
frame #1: 0x00007fff59f56bf1 libsystem_pthread.dylib`pthread_kill + 284
frame #2: 0x00007fff59e056a6 libsystem_c.dylib`abort + 127
frame #3: 0x00007fff56fe1641 libc++abi.dylib`abort_message + 231
frame #4: 0x00007fff56fedad2 libc++abi.dylib`__cxa_pure_virtual + 18
frame #5: 0x0000000100030a7f node`node::MemoryRetainerNode::MemoryRetainerNode(this=0x0000000105f16610, tracker=<unavailable>, retainer=<unavailable>) at memory_tracker-inl.h:32:24 [opt]
frame #6: 0x00000001000306e7 node`node::MemoryTracker::AddNode(node::MemoryRetainer const*, char const*) [inlined] node::MemoryRetainerNode::MemoryRetainerNode(this=0x0000000105f16610, tracker=0x00007ffeefbf5f18, retainer=<unavailable>) at memory_tracker-inl.h:26:29 [opt]
frame #7: 0x00000001000306dc node`node::MemoryTracker::AddNode(this=0x00007ffeefbf5f18, retainer=<unavailable>, edge_name="session") at memory_tracker-inl.h:270 [opt]
frame #8: 0x00000001000305f9 node`node::MemoryTracker::Track(node::MemoryRetainer const*, char const*) [inlined] node::MemoryTracker::PushNode(this=0x00007ffeefbf5f18, retainer=<unavailable>, edge_name="session") at memory_tracker-inl.h:296:27 [opt]
frame #9: 0x00000001000305ee node`node::MemoryTracker::Track(this=0x00007ffeefbf5f18, retainer=<unavailable>, edge_name="session") at memory_tracker-inl.h:244 [opt]
frame #10: 0x00000001000ba20c node`node::http2::Http2Session::Http2Settings::MemoryInfo(node::MemoryTracker*) const [inlined] node::MemoryTracker::TrackField(this=<unavailable>, edge_name=<unavailable>, value=<unavailable>) at memory_tracker-inl.h:98:5 [opt]
frame #11: 0x00000001000ba1ae node`node::http2::Http2Session::Http2Settings::MemoryInfo(this=<unavailable>, tracker=0x00007ffeefbf5f18) const at node_http2.h:1108 [opt]
frame #12: 0x000000010003061f node`node::MemoryTracker::Track(this=0x00007ffeefbf5f18, retainer=<unavailable>, edge_name=<unavailable>) at memory_tracker-inl.h:245:13 [opt]
frame #13: 0x000000010004e24f node`node::MemoryTracker::TrackField(char const*, node::CleanupHookCallback const&, char const*) [inlined] node::MemoryTracker::TrackField(this=<unavailable>, edge_name=<unavailable>, value=<unavailable>) at memory_tracker-inl.h:98:5 [opt]
frame #14: 0x000000010004e23c node`node::MemoryTracker::TrackField(this=0x00007ffeefbf5f18, edge_name=0x0000000000000000, value=0x0000000102a0da50, node_name=<unavailable>) at env.cc:937 [opt]
frame #15: 0x000000010004f44f node`void node::MemoryTracker::TrackField<std::__1::unordered_set<node::CleanupHookCallback, node::CleanupHookCallback::Hash, node::CleanupHookCallback::Equal, std::__1::allocator<node::CleanupHookCallback> >, std::__1::__hash_const_iterator<std::__1::__hash_node<node::CleanupHookCallback, void*>*> >(this=0x00007ffeefbf5f18, edge_name=<unavailable>, value=size=456, node_name=<unavailable>, element_name=<unavailable>, subtract_from_self=<unavailable>) at memory_tracker-inl.h:129:5 [opt]
frame #16: 0x000000010004e487 node`node::Environment::MemoryInfo(this=0x0000000104024000, tracker=0x00007ffeefbf5f18) const at env.cc:981:12 [opt]
frame #17: 0x000000010003061f node`node::MemoryTracker::Track(this=0x00007ffeefbf5f18, retainer=<unavailable>, edge_name=<unavailable>) at memory_tracker-inl.h:245:13 [opt]
frame #18: 0x000000010004c672 node`node::Environment::BuildEmbedderGraph(isolate=<unavailable>, graph=<unavailable>, data=<unavailable>) at env.cc:949:11 [opt]
frame #19: 0x00000001005c12dc node`v8::internal::HeapProfiler::BuildEmbedderGraph(this=<unavailable>, isolate=<unavailable>, graph=<unavailable>) at heap-profiler.cc:60:5 [opt]
frame #20: 0x00000001005cb22c node`v8::internal::NativeObjectsExplorer::IterateAndExtractReferences(this=0x00007ffeefbf61e0, generator=<unavailable>) at heap-snapshot-generator.cc:1908:28 [opt]
frame #21: 0x00000001005cbe46 node`v8::internal::HeapSnapshotGenerator::GenerateSnapshot() [inlined] v8::internal::HeapSnapshotGenerator::FillReferences(this=<unavailable>) at heap-snapshot-generator.cc:2039:24 [opt]
frame #22: 0x00000001005cbe28 node`v8::internal::HeapSnapshotGenerator::GenerateSnapshot(this=0x00007ffeefbf60f8) at heap-snapshot-generator.cc:2002 [opt]
frame #23: 0x00000001005c1351 node`v8::internal::HeapProfiler::TakeSnapshot(this=0x0000000102b04dc0, control=<unavailable>, resolver=<unavailable>) at heap-profiler.cc:70:20 [opt]
frame #24: 0x000000010005457e node`node::heap::TriggerHeapSnapshot(v8::FunctionCallbackInfo<v8::Value> const&) [inlined] node::heap::(anonymous namespace)::TakeSnapshot(isolate=<unavailable>, out=<unavailable>) at heap_utils.cc:324:35 [opt]
frame #25: 0x000000010005456d node`node::heap::TriggerHeapSnapshot(v8::FunctionCallbackInfo<v8::Value> const&) [inlined] node::heap::(anonymous namespace)::WriteSnapshot(isolate=<unavailable>, filename=<unavailable>) at heap_utils.cc:334 [opt]
frame #26: 0x0000000100054540 node`node::heap::TriggerHeapSnapshot(args=0x00007ffeefbf6740) at heap_utils.cc:376 [opt]
frame #27: 0x000000010024707c node`v8::internal::FunctionCallbackArguments::Call(this=0x00007ffeefbf67a0, handler=<unavailable>) at api-arguments-inl.h:157:3 [opt]
frame #28: 0x000000010024663d node`v8::internal::MaybeHandle<v8::internal::Object> v8::internal::(anonymous namespace)::HandleApiCallHelper<false>(isolate=0x000000010285c000, function=<unavailable>, new_target=<unavailable>, fun_data=<unavailable>, receiver=<unavailable>, args=BuiltinArguments @ 0x00007ffeefbf6840) at builtins-api.cc:109:36 [opt]
frame #29: 0x0000000100245d32 node`v8::internal::Builtin_Impl_HandleApiCall(args=<unavailable>, isolate=0x000000010285c000) at builtins-api.cc:139:5 [opt]
frame #30: 0x0000000100938359 node`Builtins_CEntry_Return1_DontSaveFPRegs_ArgvOnStack_NoBuiltinExit + 57
frame #31: 0x00000001008ad5c4 node`Builtins_InterpreterEntryTrampoline + 676
frame #32: 0x00000001008ad5c4 node`Builtins_InterpreterEntryTrampoline + 676
frame #33: 0x00000001008ad5c4 node`Builtins_InterpreterEntryTrampoline + 676
frame #34: 0x00000001008ad5c4 node`Builtins_InterpreterEntryTrampoline + 676
frame #35: 0x00000001008ad5c4 node`Builtins_InterpreterEntryTrampoline + 676
frame #36: 0x00000001008ad5c4 node`Builtins_InterpreterEntryTrampoline + 676
frame #37: 0x00000001008ad5c4 node`Builtins_InterpreterEntryTrampoline + 676
frame #38: 0x00000001008ad5c4 node`Builtins_InterpreterEntryTrampoline + 676
frame #39: 0x00000001008aaf3d node`Builtins_JSEntryTrampoline + 93
frame #40: 0x00000001008aacb8 node`Builtins_JSEntry + 120
frame #41: 0x000000010033c09e node`v8::internal::(anonymous namespace)::Invoke(v8::internal::Isolate*, v8::internal::(anonymous namespace)::InvokeParams const&) [inlined] v8::internal::GeneratedCode<unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, long, unsigned long**>::Call(this=<unavailable>, args=<unavailable>, args=<unavailable>, args=<unavailable>, args=<unavailable>, args=<unavailable>, args=<unavailable>) at simulator.h:138:12 [opt]
frame #42: 0x000000010033c09c node`v8::internal::(anonymous namespace)::Invoke(isolate=0x000000010285c000, params=0x00007ffeefbf6eb8)::InvokeParams const&) at execution.cc:266 [opt]
frame #43: 0x000000010033bddb node`v8::internal::Execution::Call(isolate=0x000000010285c000, callable=<unavailable>, receiver=<unavailable>, argc=2, argv=0x00007ffeefbf7160) at execution.cc:358:10 [opt]
frame #44: 0x00000001001dad8b node`v8::Function::Call(this=0x0000000104020818, context=<unavailable>, recv=<unavailable>, argc=2, argv=0x00007ffeefbf7160) at api.cc:4989:7 [opt]
frame #45: 0x00000001000186af node`node::InternalMakeCallback(env=<unavailable>, recv=<unavailable>, callback=<unavailable>, argc=<unavailable>, argv=0x00007ffeefbf7160, asyncContext=(async_id = 2, trigger_async_id = 1)) at callback.cc:153:21 [opt]
frame #46: 0x000000010002944b node`node::AsyncWrap::MakeCallback(this=<unavailable>, cb=(val_ = 0x0000000104020818), argc=2, argv=0x00007ffeefbf7160) at async_wrap.cc:718:27 [opt]
frame #47: 0x0000000100035d5f node`node::ConnectionWrap<node::TCPWrap, uv_tcp_s>::OnConnection(uv_stream_s*, int) [inlined] node::AsyncWrap::MakeCallback(this=0x0000000102930a20, symbol=<unavailable>, argc=2) at async_wrap-inl.h:95:10 [opt]
frame #48: 0x0000000100035d28 node`node::ConnectionWrap<node::TCPWrap, uv_tcp_s>::OnConnection(uv_stream_s*, int) [inlined] node::AsyncWrap::MakeCallback(this=0x0000000102930a20, symbol=<unavailable>, argc=2) at async_wrap-inl.h:71 [opt]
frame #49: 0x0000000100035d28 node`node::ConnectionWrap<node::TCPWrap, uv_tcp_s>::OnConnection(handle=<unavailable>, status=<unavailable>) at connection_wrap.cc:73 [opt]
frame #50: 0x000000010089c5de node`uv__server_io(loop=0x0000000101855630, w=0x0000000102930b40, events=<unavailable>) at stream.c:570:5 [opt]
frame #51: 0x00000001008a2d60 node`uv__io_poll(loop=<unavailable>, timeout=<unavailable>) at kqueue.c:0:11 [opt]
frame #52: 0x0000000100893487 node`uv_run(loop=0x0000000101855630, mode=UV_RUN_DEFAULT) at core.c:368:5 [opt]
frame #53: 0x00000001000c1c2c node`node::NodeMainInstance::Run(this=0x00007ffeefbff3e0) at node_main_instance.cc:120:9 [opt]
frame #54: 0x000000010006cbe2 node`node::Start(argc=<unavailable>, argv=<unavailable>) at node.cc:976:38 [opt]
frame #55: 0x00007fff59d603d5 libdyld.dylib`start + 1
cc @addaleax @nodejs/http2
Core dump fixed, but Http2Session leak already exist. @addaleax
Please take a snapshot for the http2 server when running the http2 connect/close a little while. (see above sample code)
@smile21 I don鈥檛 think there鈥檚 a real memory leak here, but rather an underestimation of the actual memory usage by the JS engine; https://github.com/nodejs/node/pull/28645 should address that.
Most helpful comment
I can reproduce it on master. I used the v8 API instead of the devtools for the ease of reproducing.
See stack trace
I also get
Pure virtual function calledsometimes, there may be a use-after-free for the reference fromHttp2SettingstoHttp2Session- something is holding onto theHttp2Settingswhen itsHttp2Sessionis already gone.See stack trace
cc @addaleax @nodejs/http2