Skip to content

Commit ebad043

Browse files
addaleaxjasnell
authored andcommitted
src: notify V8 for low memory when alloc fails
Call `v8::Isolate::GetCurrent()->LowMemoryNotification()` when an allocation fails to give V8 a chance to clean up and return memory before retrying (and possibly giving up). PR-URL: #8482 Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Michael Dawson <michael_dawson@ca.ibm.com> Reviewed-By: Ilkka Myller <ilkka.myller@nodefield.com>
1 parent aed9792 commit ebad043

File tree

6 files changed

+34
-1
lines changed

6 files changed

+34
-1
lines changed

src/node.cc

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,8 @@ bool trace_warnings = false;
183183
// that is used by lib/module.js
184184
bool config_preserve_symlinks = false;
185185

186+
bool v8_initialized = false;
187+
186188
// process-relative uptime base, initialized at start-up
187189
static double prog_start_time;
188190
static bool debugger_running;
@@ -4490,6 +4492,7 @@ int Start(int argc, char** argv) {
44904492

44914493
v8_platform.Initialize(v8_thread_pool_size);
44924494
V8::Initialize();
4495+
v8_initialized = true;
44934496

44944497
int exit_code = 1;
44954498
{
@@ -4503,6 +4506,7 @@ int Start(int argc, char** argv) {
45034506
StartNodeInstance(&instance_data);
45044507
exit_code = instance_data.exit_code();
45054508
}
4509+
v8_initialized = false;
45064510
V8::Dispose();
45074511

45084512
v8_platform.Dispose();

src/node_internals.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,9 @@ namespace node {
3737
// that is used by lib/module.js
3838
extern bool config_preserve_symlinks;
3939

40+
// Tells whether it is safe to call v8::Isolate::GetCurrent().
41+
extern bool v8_initialized;
42+
4043
// Forward declaration
4144
class Environment;
4245

src/util-inl.h

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -253,7 +253,15 @@ T* UncheckedRealloc(T* pointer, size_t n) {
253253
return nullptr;
254254
}
255255

256-
return static_cast<T*>(realloc(pointer, full_size));
256+
void* allocated = realloc(pointer, full_size);
257+
258+
if (UNLIKELY(allocated == nullptr)) {
259+
// Tell V8 that memory is low and retry.
260+
LowMemoryNotification();
261+
allocated = realloc(pointer, full_size);
262+
}
263+
264+
return static_cast<T*>(allocated);
257265
}
258266

259267
// As per spec realloc behaves like malloc if passed nullptr.

src/util.cc

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,4 +77,13 @@ BufferValue::BufferValue(Isolate* isolate, Local<Value> value) {
7777
}
7878
}
7979

80+
void LowMemoryNotification() {
81+
if (v8_initialized) {
82+
auto isolate = v8::Isolate::GetCurrent();
83+
if (isolate != nullptr) {
84+
isolate->LowMemoryNotification();
85+
}
86+
}
87+
}
88+
8089
} // namespace node

src/util.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,11 @@ inline char* Calloc(size_t n) { return Calloc<char>(n); }
5353
inline char* UncheckedMalloc(size_t n) { return UncheckedMalloc<char>(n); }
5454
inline char* UncheckedCalloc(size_t n) { return UncheckedCalloc<char>(n); }
5555

56+
// Used by the allocation functions when allocation fails.
57+
// Thin wrapper around v8::Isolate::LowMemoryNotification() that checks
58+
// whether V8 is initialized.
59+
void LowMemoryNotification();
60+
5661
#ifdef __GNUC__
5762
#define NO_RETURN __attribute__((noreturn))
5863
#else

test/cctest/util.cc

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,10 @@ TEST(UtilTest, ToLower) {
9090
EXPECT_EQ('a', ToLower('A'));
9191
}
9292

93+
namespace node {
94+
void LowMemoryNotification() {}
95+
}
96+
9397
TEST(UtilTest, Malloc) {
9498
using node::Malloc;
9599
EXPECT_NE(nullptr, Malloc<char>(0));

0 commit comments

Comments
 (0)