diff --git a/ext/mini_racer_extension/mini_racer_extension.cc b/ext/mini_racer_extension/mini_racer_extension.cc index 3f5d996..9414407 100644 --- a/ext/mini_racer_extension/mini_racer_extension.cc +++ b/ext/mini_racer_extension/mini_racer_extension.cc @@ -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); diff --git a/test/test_forking.rb b/test/test_forking.rb new file mode 100644 index 0000000..d145038 --- /dev/null +++ b/test/test_forking.rb @@ -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}" } + +