Skip to content

Commit e18df46

Browse files
addaleaxMylesBorins
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). Backport-PR-URL: #16587 PR-URL: #8482 Reviewed-By: Ben Noordhuis <[email protected]> Reviewed-By: James M Snell <[email protected]> Reviewed-By: Michael Dawson <[email protected]> Reviewed-By: Ilkka Myller <[email protected]>
1 parent 6a0eb9f commit e18df46

File tree

5 files changed

+29
-1
lines changed

5 files changed

+29
-1
lines changed

src/node.cc

+3
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,7 @@ bool trace_warnings = false;
198198
// that is used by lib/module.js
199199
bool config_preserve_symlinks = false;
200200

201+
bool v8_initialized = false;
201202

202203
// Set in node.cc by ParseArgs when --expose-internals or --expose_internals is
203204
// used.
@@ -4895,6 +4896,7 @@ int Start(int argc, char** argv) {
48954896

48964897
v8_platform.Initialize(v8_thread_pool_size);
48974898
V8::Initialize();
4899+
v8_initialized = true;
48984900

48994901
int exit_code = 1;
49004902
{
@@ -4908,6 +4910,7 @@ int Start(int argc, char** argv) {
49084910
StartNodeInstance(&instance_data);
49094911
exit_code = instance_data.exit_code();
49104912
}
4913+
v8_initialized = false;
49114914
V8::Dispose();
49124915

49134916
v8_platform.Dispose();

src/node_internals.h

+3
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,9 @@ extern std::string openssl_config;
4343
// that is used by lib/module.js
4444
extern bool config_preserve_symlinks;
4545

46+
// Tells whether it is safe to call v8::Isolate::GetCurrent().
47+
extern bool v8_initialized;
48+
4649
// Set in node.cc by ParseArgs when --expose-internals or --expose_internals is
4750
// used.
4851
// Used in node_config.cc to set a constant on process.binding('config')

src/util-inl.h

+9-1
Original file line numberDiff line numberDiff line change
@@ -344,7 +344,15 @@ T* UncheckedRealloc(T* pointer, size_t n) {
344344
return nullptr;
345345
}
346346

347-
return static_cast<T*>(realloc(pointer, full_size));
347+
void* allocated = realloc(pointer, full_size);
348+
349+
if (UNLIKELY(allocated == nullptr)) {
350+
// Tell V8 that memory is low and retry.
351+
LowMemoryNotification();
352+
allocated = realloc(pointer, full_size);
353+
}
354+
355+
return static_cast<T*>(allocated);
348356
}
349357

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

src/util.cc

+9
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

+5
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

0 commit comments

Comments
 (0)