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
|
@ -156,7 +156,8 @@ static std::mutex platform_lock;
|
|||
|
||||
static pthread_attr_t *thread_attr_p;
|
||||
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) {
|
||||
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();
|
||||
|
||||
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));
|
||||
} else {
|
||||
platform_already_initialized = true;
|
||||
|
@ -1221,11 +1225,16 @@ IsolateInfo::~IsolateInfo() {
|
|||
"it can not be disposed and memory will not be "
|
||||
"reclaimed till the Ruby process exits.\n");
|
||||
} else {
|
||||
if (this->pid != getpid()) {
|
||||
if (this->pid != getpid() && !single_threaded) {
|
||||
fprintf(stderr, "WARNING: V8 isolate was forked, "
|
||||
"it can not be disposed and "
|
||||
"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 {
|
||||
isolate->Dispose();
|
||||
}
|
||||
|
@ -1640,6 +1649,7 @@ static void set_ruby_exiting(VALUE value) {
|
|||
(void)value;
|
||||
|
||||
int res = pthread_rwlock_wrlock(&exit_lock);
|
||||
|
||||
ruby_exiting = true;
|
||||
if (res == 0) {
|
||||
pthread_rwlock_unlock(&exit_lock);
|
||||
|
|
|
@ -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 New Issue