Skip to content

Commit

Permalink
src: notify V8 for low memory when alloc fails
Browse files Browse the repository at this point in the history
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 <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>
  • Loading branch information
addaleax authored and MylesBorins committed Nov 14, 2017
1 parent 6a0eb9f commit e18df46
Show file tree
Hide file tree
Showing 5 changed files with 29 additions and 1 deletion.
3 changes: 3 additions & 0 deletions src/node.cc
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,7 @@ bool trace_warnings = false;
// that is used by lib/module.js
bool config_preserve_symlinks = false;

bool v8_initialized = false;

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

v8_platform.Initialize(v8_thread_pool_size);
V8::Initialize();
v8_initialized = true;

int exit_code = 1;
{
Expand All @@ -4908,6 +4910,7 @@ int Start(int argc, char** argv) {
StartNodeInstance(&instance_data);
exit_code = instance_data.exit_code();
}
v8_initialized = false;
V8::Dispose();

v8_platform.Dispose();
Expand Down
3 changes: 3 additions & 0 deletions src/node_internals.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,9 @@ extern std::string openssl_config;
// that is used by lib/module.js
extern bool config_preserve_symlinks;

// Tells whether it is safe to call v8::Isolate::GetCurrent().
extern bool v8_initialized;

// Set in node.cc by ParseArgs when --expose-internals or --expose_internals is
// used.
// Used in node_config.cc to set a constant on process.binding('config')
Expand Down
10 changes: 9 additions & 1 deletion src/util-inl.h
Original file line number Diff line number Diff line change
Expand Up @@ -344,7 +344,15 @@ T* UncheckedRealloc(T* pointer, size_t n) {
return nullptr;
}

return static_cast<T*>(realloc(pointer, full_size));
void* allocated = realloc(pointer, full_size);

if (UNLIKELY(allocated == nullptr)) {
// Tell V8 that memory is low and retry.
LowMemoryNotification();
allocated = realloc(pointer, full_size);
}

return static_cast<T*>(allocated);
}

// As per spec realloc behaves like malloc if passed nullptr.
Expand Down
9 changes: 9 additions & 0 deletions src/util.cc
Original file line number Diff line number Diff line change
Expand Up @@ -77,4 +77,13 @@ BufferValue::BufferValue(Isolate* isolate, Local<Value> value) {
}
}

void LowMemoryNotification() {
if (v8_initialized) {
auto isolate = v8::Isolate::GetCurrent();
if (isolate != nullptr) {
isolate->LowMemoryNotification();
}
}
}

} // namespace node
5 changes: 5 additions & 0 deletions src/util.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,11 @@ inline char* Calloc(size_t n) { return Calloc<char>(n); }
inline char* UncheckedMalloc(size_t n) { return UncheckedMalloc<char>(n); }
inline char* UncheckedCalloc(size_t n) { return UncheckedCalloc<char>(n); }

// Used by the allocation functions when allocation fails.
// Thin wrapper around v8::Isolate::LowMemoryNotification() that checks
// whether V8 is initialized.
void LowMemoryNotification();

#ifdef __GNUC__
#define NO_RETURN __attribute__((noreturn))
#else
Expand Down

0 comments on commit e18df46

Please sign in to comment.