Skip to content

Commit

Permalink
FEATURE: warn more loudly about forked environments
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
SamSaffron committed Sep 15, 2020
1 parent 94cdb03 commit 86bdc6d
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 3 deletions.
16 changes: 13 additions & 3 deletions ext/mini_racer_extension/mini_racer_extension.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -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();
}
Expand Down Expand Up @@ -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);
Expand Down
25 changes: 25 additions & 0 deletions test/test_forking.rb
Original file line number Diff line number Diff line change
@@ -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}" }


0 comments on commit 86bdc6d

Please sign in to comment.