Browse Source
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: 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>
v6
Anna Henningsen
9 years ago
No known key found for this signature in database
GPG Key ID: D8B9F5AEAE84E4CF
6 changed files with
34 additions and
1 deletions
src/node.cc
src/node_internals.h
src/util-inl.h
src/util.cc
src/util.h
test/cctest/util.cc
@ -183,6 +183,8 @@ bool trace_warnings = false;
// that is used by lib/module.js
// that is used by lib/module.js
bool config_preserve_symlinks = false ;
bool config_preserve_symlinks = false ;
bool v8_initialized = false ;
// process-relative uptime base, initialized at start-up
// process-relative uptime base, initialized at start-up
static double prog_start_time ;
static double prog_start_time ;
static bool debugger_running ;
static bool debugger_running ;
@ -4490,6 +4492,7 @@ int Start(int argc, char** argv) {
v8_platform . Initialize ( v8_thread_pool_size ) ;
v8_platform . Initialize ( v8_thread_pool_size ) ;
V8 : : Initialize ( ) ;
V8 : : Initialize ( ) ;
v8_initialized = true ;
int exit_code = 1 ;
int exit_code = 1 ;
{
{
@ -4503,6 +4506,7 @@ int Start(int argc, char** argv) {
StartNodeInstance ( & instance_data ) ;
StartNodeInstance ( & instance_data ) ;
exit_code = instance_data . exit_code ( ) ;
exit_code = instance_data . exit_code ( ) ;
}
}
v8_initialized = false ;
V8 : : Dispose ( ) ;
V8 : : Dispose ( ) ;
v8_platform . Dispose ( ) ;
v8_platform . Dispose ( ) ;
@ -37,6 +37,9 @@ namespace node {
// that is used by lib/module.js
// that is used by lib/module.js
extern bool config_preserve_symlinks ;
extern bool config_preserve_symlinks ;
// Tells whether it is safe to call v8::Isolate::GetCurrent().
extern bool v8_initialized ;
// Forward declaration
// Forward declaration
class Environment ;
class Environment ;
@ -253,7 +253,15 @@ T* UncheckedRealloc(T* pointer, size_t n) {
return nullptr ;
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.
// As per spec realloc behaves like malloc if passed nullptr.
@ -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
} // namespace node
@ -44,6 +44,11 @@ inline char* Calloc(size_t n) { return Calloc<char>(n); }
inline char * UncheckedMalloc ( size_t n ) { return UncheckedMalloc < char > ( n ) ; }
inline char * UncheckedMalloc ( size_t n ) { return UncheckedMalloc < char > ( n ) ; }
inline char * UncheckedCalloc ( size_t n ) { return UncheckedCalloc < 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__
# ifdef __GNUC__
# define NO_RETURN __attribute__((noreturn))
# define NO_RETURN __attribute__((noreturn))
# else
# else
@ -90,6 +90,10 @@ TEST(UtilTest, ToLower) {
EXPECT_EQ ( ' a ' , ToLower ( ' A ' ) ) ;
EXPECT_EQ ( ' a ' , ToLower ( ' A ' ) ) ;
}
}
namespace node {
void LowMemoryNotification ( ) { }
}
TEST ( UtilTest , Malloc ) {
TEST ( UtilTest , Malloc ) {
using node : : Malloc ;
using node : : Malloc ;
EXPECT_NE ( nullptr , Malloc < char > ( 0 ) ) ;
EXPECT_NE ( nullptr , Malloc < char > ( 0 ) ) ;