Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
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>
  • Loading branch information
addaleax authored and bnoordhuis committed Oct 29, 2017
commit 618ca4276d344be2c6d1ebfe22df5fbe8c3c9fef
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