Skip to content

Commit 5c38c70

Browse files
committed
FIX: release heap snapshot buffers
Free native buffers after heap snapshots and low memory notifications to avoid leaking memory. Delete the V8 heap snapshot once it has been serialized.
1 parent f1932aa commit 5c38c70

3 files changed

Lines changed: 19 additions & 1 deletion

File tree

CHANGELOG

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
- (Unreleased)
22
- Add `Context#perform_microtask_checkpoint` to synchronously drain the V8 microtask queue, useful for spec-compliant `dispatchEvent` sequencing inside Ruby callbacks
3+
- Fix native memory leaks in `Context#heap_snapshot`/`Context#write_heap_snapshot`; thanks to Pranjali Thakur from depthfrist.com
34

45
- 0.21.1 - 25-05-2026
56
- Run `:single_threaded` V8 dispatches on a reusable mini_racer-owned native thread so V8 does not execute on Ruby-owned threads

ext/mini_racer_extension/mini_racer_extension.c

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1458,6 +1458,20 @@ static VALUE context_heap_stats(VALUE self)
14581458
return h;
14591459
}
14601460

1461+
static VALUE buf_reset_ensure(VALUE arg)
1462+
{
1463+
buf_reset((Buf *)arg);
1464+
return Qnil;
1465+
}
1466+
1467+
static VALUE heap_snapshot_to_str(VALUE arg)
1468+
{
1469+
Buf *res;
1470+
1471+
res = (Buf *)arg;
1472+
return rb_utf8_str_new((char *)res->buf, res->len);
1473+
}
1474+
14611475
static VALUE context_heap_snapshot(VALUE self)
14621476
{
14631477
Buf req, res;
@@ -1467,7 +1481,8 @@ static VALUE context_heap_snapshot(VALUE self)
14671481
buf_init(&req);
14681482
buf_putc(&req, 'H'); // (H)eap snapshot, returns plain bytes
14691483
rendezvous_no_des(c, &req, &res); // takes ownership of |req|
1470-
return rb_utf8_str_new((char *)res.buf, res.len);
1484+
return rb_ensure(heap_snapshot_to_str, (VALUE)&res,
1485+
buf_reset_ensure, (VALUE)&res);
14711486
}
14721487

14731488
static VALUE context_perform_microtask_checkpoint(VALUE self)
@@ -1501,6 +1516,7 @@ static VALUE context_low_memory_notification(VALUE self)
15011516
buf_init(&req);
15021517
buf_putc(&req, 'L'); // (L)ow memory notification, returns nothing
15031518
rendezvous_no_des(c, &req, &res); // takes ownership of |req|
1519+
buf_reset(&res);
15041520
return Qnil;
15051521
}
15061522

ext/mini_racer_extension/mini_racer_v8.cc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -659,6 +659,7 @@ extern "C" void v8_heap_snapshot(State *pst)
659659
auto snapshot = st.isolate->GetHeapProfiler()->TakeHeapSnapshot();
660660
OutputStream os;
661661
snapshot->Serialize(&os, v8::HeapSnapshot::kJSON);
662+
const_cast<v8::HeapSnapshot*>(snapshot)->Delete();
662663
v8_reply(st.ruby_context, os.buf.data(), os.buf.size()); // not serialized because big
663664
}
664665

0 commit comments

Comments
 (0)