summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnna Henningsen <anna@addaleax.net>2016-09-10 18:21:20 +0200
committerMyles Borins <mylesborins@google.com>2017-11-14 13:57:35 -0500
commite18df46092624980a0218982af757a0743cf1d98 (patch)
tree14b26cee5700fa86ba236e08a6ec906f2930f597
parent6a0eb9f6cfbe3c76a3508418997de7ab2becd4b5 (diff)
downloadnode-new-e18df46092624980a0218982af757a0743cf1d98.tar.gz
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: https://github.com/nodejs/node/pull/16587 PR-URL: https://github.com/nodejs/node/pull/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>
-rw-r--r--src/node.cc3
-rw-r--r--src/node_internals.h3
-rw-r--r--src/util-inl.h10
-rw-r--r--src/util.cc9
-rw-r--r--src/util.h5
5 files changed, 29 insertions, 1 deletions
diff --git a/src/node.cc b/src/node.cc
index 6345abdb31..98fde0dbbe 100644
--- a/src/node.cc
+++ b/src/node.cc
@@ -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.
@@ -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;
{
@@ -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();
diff --git a/src/node_internals.h b/src/node_internals.h
index 130af5d1c0..9ead8b1037 100644
--- a/src/node_internals.h
+++ b/src/node_internals.h
@@ -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')
diff --git a/src/util-inl.h b/src/util-inl.h
index 886b8569d6..5ffe5b857f 100644
--- a/src/util-inl.h
+++ b/src/util-inl.h
@@ -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.
diff --git a/src/util.cc b/src/util.cc
index 14aa68996f..9fb5c3fd28 100644
--- a/src/util.cc
+++ b/src/util.cc
@@ -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
diff --git a/src/util.h b/src/util.h
index 8b2db6f5c3..4ce25e4622 100644
--- a/src/util.h
+++ b/src/util.h
@@ -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