mirror of
https://github.com/rubyjs/mini_racer
synced 2023-03-27 23:21:28 -04:00
FEATURE: warn more loudly about forked environments
In single_threaded mode MiniRacer will behave far more reasonably if platform is initialized in the master process. Sadly this is only a partial solution since we will hang at: ``` #0 0x00007fe6f037e34d in pthread_cond_broadcast@@GLIBC_2.3.2 () from /usr/lib/libpthread.so.0 #1 0x00007fe6ebc15c05 in v8::platform::DelayedTaskQueue::Terminate() () from /home/sam/Source/mini_racer/lib/mini_racer_extension.so #2 0x00007fe6ebc14dfd in v8::platform::DefaultWorkerThreadsTaskRunner::Terminate() () from /home/sam/Source/mini_racer/lib/mini_racer_extension.so #3 0x00007fe6ebc13bd6 in v8::platform::DefaultPlatform::~DefaultPlatform() () from /home/sam/Source/mini_racer/lib/mini_racer_extension.so #4 0x00007fe6ebc13cde in v8::platform::DefaultPlatform::~DefaultPlatform() () from /home/sam/Source/mini_racer/lib/mini_racer_extension.so #5 0x00007fe6effb0db7 in __run_exit_handlers () from /usr/lib/libc.so.6 ``` Likely some more v8 changes are needed to mitigate the heavily forked use case.
This commit is contained in:
parent
94cdb03211
commit
86bdc6d942
2 changed files with 38 additions and 3 deletions
|
@ -156,7 +156,8 @@ static std::mutex platform_lock;
|
||||||
|
|
||||||
static pthread_attr_t *thread_attr_p;
|
static pthread_attr_t *thread_attr_p;
|
||||||
static pthread_rwlock_t exit_lock = PTHREAD_RWLOCK_INITIALIZER;
|
static pthread_rwlock_t exit_lock = PTHREAD_RWLOCK_INITIALIZER;
|
||||||
static bool ruby_exiting; // guarded by exit_lock
|
static bool ruby_exiting = false; // guarded by exit_lock
|
||||||
|
static bool single_threaded = false;
|
||||||
|
|
||||||
static VALUE rb_platform_set_flag_as_str(VALUE _klass, VALUE flag_as_str) {
|
static VALUE rb_platform_set_flag_as_str(VALUE _klass, VALUE flag_as_str) {
|
||||||
bool platform_already_initialized = false;
|
bool platform_already_initialized = false;
|
||||||
|
@ -169,6 +170,9 @@ static VALUE rb_platform_set_flag_as_str(VALUE _klass, VALUE flag_as_str) {
|
||||||
platform_lock.lock();
|
platform_lock.lock();
|
||||||
|
|
||||||
if (current_platform == NULL) {
|
if (current_platform == NULL) {
|
||||||
|
if (!strcmp(RSTRING_PTR(flag_as_str), "--single_threaded")) {
|
||||||
|
single_threaded = true;
|
||||||
|
}
|
||||||
V8::SetFlagsFromString(RSTRING_PTR(flag_as_str), (int)RSTRING_LEN(flag_as_str));
|
V8::SetFlagsFromString(RSTRING_PTR(flag_as_str), (int)RSTRING_LEN(flag_as_str));
|
||||||
} else {
|
} else {
|
||||||
platform_already_initialized = true;
|
platform_already_initialized = true;
|
||||||
|
@ -1221,11 +1225,16 @@ IsolateInfo::~IsolateInfo() {
|
||||||
"it can not be disposed and memory will not be "
|
"it can not be disposed and memory will not be "
|
||||||
"reclaimed till the Ruby process exits.\n");
|
"reclaimed till the Ruby process exits.\n");
|
||||||
} else {
|
} else {
|
||||||
if (this->pid != getpid()) {
|
if (this->pid != getpid() && !single_threaded) {
|
||||||
fprintf(stderr, "WARNING: V8 isolate was forked, "
|
fprintf(stderr, "WARNING: V8 isolate was forked, "
|
||||||
"it can not be disposed and "
|
"it can not be disposed and "
|
||||||
"memory will not be reclaimed "
|
"memory will not be reclaimed "
|
||||||
"till the Ruby process exits.\n");
|
"till the Ruby process exits.\n"
|
||||||
|
"It is VERY likely your process will hang.\n"
|
||||||
|
"If you wish to use v8 in forked environment "
|
||||||
|
"please ensure the platform is initialized with:\n"
|
||||||
|
"MiniRacer::Platform.set_flags! :single_threaded\n"
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
isolate->Dispose();
|
isolate->Dispose();
|
||||||
}
|
}
|
||||||
|
@ -1640,6 +1649,7 @@ static void set_ruby_exiting(VALUE value) {
|
||||||
(void)value;
|
(void)value;
|
||||||
|
|
||||||
int res = pthread_rwlock_wrlock(&exit_lock);
|
int res = pthread_rwlock_wrlock(&exit_lock);
|
||||||
|
|
||||||
ruby_exiting = true;
|
ruby_exiting = true;
|
||||||
if (res == 0) {
|
if (res == 0) {
|
||||||
pthread_rwlock_unlock(&exit_lock);
|
pthread_rwlock_unlock(&exit_lock);
|
||||||
|
|
25
test/test_forking.rb
Normal file
25
test/test_forking.rb
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
$LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
|
||||||
|
require 'mini_racer'
|
||||||
|
|
||||||
|
MiniRacer::Platform.set_flags! :single_threaded
|
||||||
|
|
||||||
|
@ctx = MiniRacer::Context.new
|
||||||
|
@ctx.eval("var a = 1+1")
|
||||||
|
|
||||||
|
def trigger_gc
|
||||||
|
puts "a"
|
||||||
|
ctx = MiniRacer::Context.new
|
||||||
|
puts "b"
|
||||||
|
ctx.eval("var a = #{('x' * 100000).inspect}")
|
||||||
|
puts "c"
|
||||||
|
ctx.eval("a = undefined")
|
||||||
|
puts "d"
|
||||||
|
ctx.isolate.low_memory_notification
|
||||||
|
puts "f"
|
||||||
|
puts "done triggering"
|
||||||
|
end
|
||||||
|
|
||||||
|
trigger_gc
|
||||||
|
Process.wait fork { puts @ctx.eval("a"); @ctx.dispose; puts Process.pid; trigger_gc; puts "done #{Process.pid}" }
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue