Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ToObject: It is more thread safe to use isolate passed explicitly rather than relying on it retrieved via a static call in constructor. #310

Merged
merged 1 commit into from
Jul 21, 2017

Conversation

matiwinnetou
Copy link
Contributor

@matiwinnetou matiwinnetou commented Jul 18, 2017

Fixes #309. Perhaps there is more elegant fix but this already helps us in production on multi concurrent access and our rendering pool from V8s to serve pages.

@matiwinnetou matiwinnetou force-pushed the issue-309 branch 2 times, most recently from 7535eea to e2a8cc5 Compare July 18, 2017 21:52
@matiwinnetou matiwinnetou changed the title Pass isolate explicitly, fixes: #309 ToObject: It is more secure (thread safe) to use isolate passed explicitly rather than relying on it retrieved via a static call in constructor. Jul 19, 2017
@matiwinnetou matiwinnetou changed the title ToObject: It is more secure (thread safe) to use isolate passed explicitly rather than relying on it retrieved via a static call in constructor. ToObject: It is more thread safe to use isolate passed explicitly rather than relying on it retrieved via a static call in constructor. Jul 19, 2017
@matiwinnetou
Copy link
Contributor Author

matiwinnetou commented Jul 21, 2017

Still, didn't manage to fix it but situation is better, only one crash in 1,5 days across 16 machines

#
# A fatal error has been detected by the Java Runtime Environment:
#
#  SIGSEGV (0xb) at pc=0x00007fc4c9a6b872, pid=38, tid=0x00007fc4cb117700
#
# JRE version: Java(TM) SE Runtime Environment (8.0_131-b11) (build 1.8.0_131-b11)
# Java VM: Java HotSpot(TM) 64-Bit Server VM (25.131-b11 mixed mode linux-amd64 compressed oops)
# Problematic frame:
# C  [libj2v8_linux_x86_64.so+0x56f872]  v8::String::Value::Value(v8::Local<v8::Value>)+0x52
#
# Core dump written. Default location: //core or core.38
#
# If you would like to submit a bug report, please visit:
#   http://bugreport.java.com/bugreport/crash.jsp
# The crash happened outside the Java Virtual Machine in native code.
# See problematic frame for where to report the bug.
#

---------------  T H R E A D  ---------------

Current thread (0x00007fc36000b800):  JavaThread "http-nio-8080-exec-20" daemon [_thread_in_native, id=156, stack(0x00007fc4cb017000,0x00007fc4cb118000)]

siginfo: si_signo: 11 (SIGSEGV), si_code: 1 (SEGV_MAPERR), si_addr: 0x0000000000008ce8

Registers:
RAX=0x0000000000000000, RBX=0x0000000000000000, RCX=0x0000000000000000, RDX=0x00007fc4cb117a30
RSP=0x00007fc4cb1154a0, RBP=0x00007fc4cb115540, RSI=0x00007fc3ec05d0a8, RDI=0x0000000000000002
R8 =0x0000000000000000, R9 =0x00000359975ba600, R10=0x00007fc508f55a08, R11=0x00001e1900000000
R12=0x00007fc4cb1154d0, R13=0x00000000f858bb40, R14=0x00007fc4cb115990, R15=0x00007fc3ec05d0a8
RIP=0x00007fc4c9a6b872, EFLAGS=0x0000000000010246, CSGSFS=0x0000000000000033, ERR=0x0000000000000004
  TRAPNO=0x000000000000000e

Top of Stack: (sp=0x00007fc4cb1154a0)
0x00007fc4cb1154a0:   0000000000000005 00007fc4cb115510
0x00007fc4cb1154b0:   00007fc4cb1154e0 00003efbe57060c7
0x00007fc4cb1154c0:   0000000000000002 00003efbe5706001
0x00007fc4cb1154d0:   00007fc4cb1154c0 0000000000000030
0x00007fc4cb1154e0:   000000000000bba1 10f049c554aa7700
0x00007fc4cb1154f0:   00002a8ba937af31 00007fc3ec05d0a8
0x00007fc4cb115500:   0000000000000000 10f049c554aa7700
0x00007fc4cb115510:   00007fc3ec054b40 00000000c53e7db8
0x00007fc4cb115520:   0000000000000000 00000000f858bb40
0x00007fc4cb115530:   00007fc3ec054b40 00007fc36000b800
0x00007fc4cb115540:   00007fc4cb1159c0 00007fc4c9a268e4
0x00007fc4cb115550:   00007fc4cb115598 00000000e570ed5a
0x00007fc4cb115560:   00007fc4cb115a20 00007fc508f40b10
0x00007fc4cb115570:   00007fc4cb1159f0 00007fc36000b9f8
0x00007fc4cb115580:   00002a79af68beb1 0000000c00000000
0x00007fc4cb115590:   0000000c00000000 0000000c00000000
0x00007fc4cb1155a0:   00003efbe5736961 0000000c00000000
0x00007fc4cb1155b0:   00007fc3ec05d0a8 00007fc3ec05d0a8
0x00007fc4cb1155c0:   0000000000000000 00002a8ba937ace9
0x00007fc4cb1155d0:   00007fc508f4cd50 0000000000000003
0x00007fc4cb1155e0:   00007fc4cab4ec6c 00007fc4cb115718
0x00007fc4cb1155f0:   00002a252da3d6f1 0000000100000000
0x00007fc4cb115600:   00007fc4cb1156e0 00007fc4c9c37223
0x00007fc4cb115610:   00007fc4cb115620 00007fc4c9d47379
0x00007fc4cb115620:   00007fc4cb115680 00002a252da04241
0x00007fc4cb115630:   00007fc3ec064720 00000003c9d4703c
0x00007fc4cb115640:   00007fc508f4cd50 00007fc3ec05d0b8
0x00007fc4cb115650:   0000000000000000 0000000000000000
0x00007fc4cb115660:   00007fc3ec05d0a8 00007fc3ec05d0a8
0x00007fc4cb115670:   00000359975ba6c9 00000359975ba6c9
0x00007fc4cb115680:   00000359975ba6c9 00000359975ba6c9
0x00007fc4cb115690:   00000359975ba6c8 000026df57c04ca9 

Instructions: (pc=0x00007fc4c9a6b872)
0x00007fc4c9a6b852:   84 f5 00 00 00 48 8b 05 e2 23 0a 01 49 89 fe 49
0x00007fc4c9a6b862:   89 f7 4c 8d 65 90 8b 38 e8 21 d0 f6 ff 48 89 c3
0x00007fc4c9a6b872:   44 8b a8 e8 8c 00 00 48 89 85 70 ff ff ff c7 80
0x00007fc4c9a6b882:   e8 8c 00 00 03 00 00 00 48 8b 80 28 8d 00 00 48 

Register to memory mapping:

RAX=0x0000000000000000 is an unknown value
RBX=0x0000000000000000 is an unknown value
RCX=0x0000000000000000 is an unknown value
RDX=0x00007fc4cb117a30 is pointing into the stack for thread: 0x00007fc36000b800
RSP=0x00007fc4cb1154a0 is pointing into the stack for thread: 0x00007fc36000b800
RBP=0x00007fc4cb115540 is pointing into the stack for thread: 0x00007fc36000b800
RSI=0x00007fc3ec05d0a8 is an unknown value
RDI=0x0000000000000002 is an unknown value
R8 =0x0000000000000000 is an unknown value
R9 =0x00000359975ba600 is an unknown value
R10=0x00007fc508f55a08 is an unknown value
R11=0x00001e1900000000 is an unknown value
R12=0x00007fc4cb1154d0 is pointing into the stack for thread: 0x00007fc36000b800
R13=0x00000000f858bb40 is an oop
[Ljava.lang.Object; 
 - klass: 'java/lang/Object'[]
 - length: 3
R14=0x00007fc4cb115990 is pointing into the stack for thread: 0x00007fc36000b800
R15=0x00007fc3ec05d0a8 is an unknown value


Stack: [0x00007fc4cb017000,0x00007fc4cb118000],  sp=0x00007fc4cb1154a0,  free space=1017k
Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code)
C  [libj2v8_linux_x86_64.so+0x56f872]  v8::String::Value::Value(v8::Local<v8::Value>)+0x52
C  [libj2v8_linux_x86_64.so+0x52a8e4]  getResult(JNIEnv_*, _jobject*&, long, v8::Local<v8::Value>&, int)+0x732
C  [libj2v8_linux_x86_64.so+0x518be4]  Java_com_eclipsesource_v8_V8__1executeFunction__JIJLjava_lang_String_2J+0x1fb
J 10189  com.eclipsesource.v8.V8._executeFunction(JIJLjava/lang/String;J)Ljava/lang/Object; (0 bytes) @ 0x00007fc4f8b9b14d [0x00007fc4f8b9b080+0xcd]
J 12892 C2 com.eclipsesource.v8.V8Object.executeJSFunction(Ljava/lang/String;[Ljava/lang/Object;)Ljava/lang/Object; (279 bytes) @ 0x00007fc4f9fff508 [0x00007fc4f9fff1c0+0x348]
J 13578 C2 pubse.ecs.system.renderer.servlet.j2v8.PoolingJ2V8JavaScriptRenderer.apply(Lde/mobile/ecs/World;)V (340 bytes) @ 0x00007fc4fab1cfa4 [0x00007fc4fab1c780+0x824]
J 13092 C2 pubse.ecs.system.renderer.ResponseRenderer.apply(Lde/mobile/ecs/World;)V (79 bytes) @ 0x00007fc4fa92d3b4 [0x00007fc4fa92d020+0x394]
J 11516 C2 com.google.inject.internal.InterceptorStackCallback$InterceptedMethodInvocation.proceed()Ljava/lang/Object; (91 bytes) @ 0x00007fc4fa680350 [0x00007fc4fa67a3e0+0x5f70]
J 13634 C2 pubse.config.InboundModule$Monitor.invoke(Lorg/aopalliance/intercept/MethodInvocation;)Ljava/lang/Object; (70 bytes) @ 0x00007fc4f9cea5bc [0x00007fc4f9cea4a0+0x11c]
J 11516 C2 com.google.inject.internal.InterceptorStackCallback$InterceptedMethodInvocation.proceed()Ljava/lang/Object; (91 bytes) @ 0x00007fc4fa67a560 [0x00007fc4fa67a3e0+0x180]
J 12832 C2 pubse.tomcat.handler.ServletRouter$$Lambda$188.handle(Ljavax/servlet/http/HttpServletRequest;Ljavax/servlet/http/HttpServletResponse;)V (10 bytes) @ 0x00007fc4faa54520 [0x00007fc4faa53be0+0x940]
J 11093 C2 org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(Ljavax/servlet/ServletRequest;Ljavax/servlet/ServletResponse;)V (574 bytes) @ 0x00007fc4f969e020 [0x00007fc4f969dee0+0x140]
J 12551 C2 org.ocpsoft.rewrite.servlet.RewriteFilter.doFilter(Ljavax/servlet/ServletRequest;Ljavax/servlet/ServletResponse;Ljavax/servlet/FilterChain;)V (402 bytes) @ 0x00007fc4fa992a80 [0x00007fc4fa9917c0+0x12c0]
J 11093 C2 org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(Ljavax/servlet/ServletRequest;Ljavax/servlet/ServletResponse;)V (574 bytes) @ 0x00007fc4f969e328 [0x00007fc4f969dee0+0x448]
J 12771 C2 pubse.util.ServletFilters$Utf8EncodingFilter.doFilter(Ljavax/servlet/ServletRequest;Ljavax/servlet/ServletResponse;Ljavax/servlet/FilterChain;)V (21 bytes) @ 0x00007fc4faa25180 [0x00007fc4faa24da0+0x3e0]
J 11093 C2 org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(Ljavax/servlet/ServletRequest;Ljavax/servlet/ServletResponse;)V (574 bytes) @ 0x00007fc4f969e328 [0x00007fc4f969dee0+0x448]
J 12707 C2 pubse.util.ServletFilters$LoggingFilter.doFilter(Ljavax/servlet/ServletRequest;Ljavax/servlet/ServletResponse;Ljavax/servlet/FilterChain;)V (76 bytes) @ 0x00007fc4fa3bcfe8 [0x00007fc4fa3bcbe0+0x408]
J 11093 C2 org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(Ljavax/servlet/ServletRequest;Ljavax/servlet/ServletResponse;)V (574 bytes) @ 0x00007fc4f969e328 [0x00007fc4f969dee0+0x448]
J 13553 C2 org.apache.catalina.core.StandardWrapperValve.invoke(Lorg/apache/catalina/connector/Request;Lorg/apache/catalina/connector/Response;)V (1389 bytes) @ 0x00007fc4fa464fec [0x00007fc4fa464e00+0x1ec]
J 12726 C2 org.apache.catalina.authenticator.AuthenticatorBase.invoke(Lorg/apache/catalina/connector/Request;Lorg/apache/catalina/connector/Response;)V (903 bytes) @ 0x00007fc4fa5b2900 [0x00007fc4fa5b1980+0xf80]
J 12739 C2 org.apache.catalina.core.StandardHostValve.invoke(Lorg/apache/catalina/connector/Request;Lorg/apache/catalina/connector/Response;)V (402 bytes) @ 0x00007fc4faa03420 [0x00007fc4faa030c0+0x360]
J 13494 C2 org.apache.catalina.connector.CoyoteAdapter.service(Lorg/apache/coyote/Request;Lorg/apache/coyote/Response;)V (805 bytes) @ 0x00007fc4fa105994 [0x00007fc4fa1054a0+0x4f4]
J 13979 C2 org.apache.coyote.http11.AbstractHttp11Processor.process(Lorg/apache/tomcat/util/net/SocketWrapper;)Lorg/apache/tomcat/util/net/AbstractEndpoint$Handler$SocketState; (1128 bytes) @ 0x00007fc4f9b0f65c [0x00007fc4f9b0f020+0x63c]
J 13493 C2 org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(Lorg/apache/tomcat/util/net/SocketWrapper;Lorg/apache/tomcat/util/net/SocketStatus;)Lorg/apache/tomcat/util/net/AbstractEndpoint$Handler$SocketState; (1073 bytes) @ 0x00007fc4fa475960 [0x00007fc4fa475480+0x4e0]
J 13115 C2 org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun()V (603 bytes) @ 0x00007fc4fa0607fc [0x00007fc4fa060680+0x17c]
J 12608 C2 org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run()V (79 bytes) @ 0x00007fc4fa49626c [0x00007fc4fa4961c0+0xac]
J 13557% C2 java.util.concurrent.ThreadPoolExecutor.runWorker(Ljava/util/concurrent/ThreadPoolExecutor$Worker;)V (225 bytes) @ 0x00007fc4fa57c134 [0x00007fc4fa57bf20+0x214]
j  java.util.concurrent.ThreadPoolExecutor$Worker.run()V+5
j  org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run()V+4
j  java.lang.Thread.run()V+11
v  ~StubRoutines::call_stub
V  [libjvm.so+0x691d16]  JavaCalls::call_helper(JavaValue*, methodHandle*, JavaCallArguments*, Thread*)+0x1056
V  [libjvm.so+0x692221]  JavaCalls::call_virtual(JavaValue*, KlassHandle, Symbol*, Symbol*, JavaCallArguments*, Thread*)+0x321
V  [libjvm.so+0x6926c7]  JavaCalls::call_virtual(JavaValue*, Handle, KlassHandle, Symbol*, Symbol*, Thread*)+0x47
V  [libjvm.so+0x72da50]  thread_entry(JavaThread*, Thread*)+0xa0
V  [libjvm.so+0xa76833]  JavaThread::thread_main_inner()+0x103
V  [libjvm.so+0xa7697c]  JavaThread::run()+0x11c
V  [libjvm.so+0x927568]  java_start(Thread*)+0x108
C  [libpthread.so.0+0x76ba]  start_thread+0xca

@matiwinnetou
Copy link
Contributor Author

This is another case where thread local isolate does not point to the same Isolate like J2V8 is pointing.

String::Value::Value(v8::Local<v8::Value> obj) : str_(NULL), length_(0) {
  if (obj.IsEmpty()) return;
  i::Isolate* isolate = i::Isolate::Current();
  Isolate* v8_isolate = reinterpret_cast<Isolate*>(isolate);
  ENTER_V8(isolate);
  i::HandleScope scope(isolate);
  Local<Context> context = v8_isolate->GetCurrentContext();
  TryCatch try_catch(v8_isolate);
  Local<String> str;
  if (!obj->ToString(context).ToLocal(&str)) return;
  length_ = str->Length();
  str_ = i::NewArray<uint16_t>(length_ + 1);
  str->Write(str_);
}

@matiwinnetou
Copy link
Contributor Author

matiwinnetou commented Jul 21, 2017

Again I think, i::Isolate::Current(); is wrong, it is accessed from thread locals:

It somehow gets desynchronized with what is in V8 runtime defined in J2V8 in cpp layer.

from isolate.h:

  // Find the PerThread for this particular (isolate, thread) combination
  // If one does not yet exist, return null.
  PerIsolateThreadData* FindPerThreadDataForThisThread();

  // Find the PerThread for given (isolate, thread) combination
  // If one does not yet exist, return null.
  PerIsolateThreadData* FindPerThreadDataForThread(ThreadId thread_id);

  // Discard the PerThread for this particular (isolate, thread) combination
  // If one does not yet exist, no-op.
  void DiscardPerThreadDataForThisThread();

@matiwinnetou
Copy link
Contributor Author

matiwinnetou commented Jul 21, 2017

Another idea is that when Isolates desynchronize then check if Isolate pointer from here:
i::Isolate* isolate = i::Isolate::Current();

is pointing to the same Isolate like V8 in V8 (v8RuntimePtr = _createIsolate(globalAlias);)

    protected V8(final String globalAlias) {
        super(null);
        released = false;
        v8RuntimePtr = _createIsolate(globalAlias);
        locker = new V8Locker(this);
        checkThread();
        objectHandle = _getGlobalObject(v8RuntimePtr);
    }

If it is not pointing this means V8 runtime has been AUTO released.

@matiwinnetou
Copy link
Contributor Author

matiwinnetou commented Jul 21, 2017

@irbull Have you noticed that when Isolate::Scope is created we immediately call enter on it in constructor?

  class V8_EXPORT Scope {
   public:
    explicit Scope(Isolate* isolate) : isolate_(isolate) {
      isolate->Enter();
    }

    ~Scope() { isolate_->Exit(); }

   private:
    Isolate* const isolate_;

    // Prevent copying of Scope objects.
    Scope(const Scope&);
    Scope& operator=(const Scope&);
  };

this means that when we createIsolate in Java_com_eclipsesource_v8_V8__1createIsolate, then we immediately enter isolate...

@irbull
Copy link
Member

irbull commented Jul 21, 2017

I like both #310 and #308. These APIs didn't exist when I first wrote J2V8, but I think they are the way to go. With these two together, are you still seeing crashes?

@matiwinnetou
Copy link
Contributor Author

@irbull I do see the crash and I exactly know why

@matiwinnetou
Copy link
Contributor Author

matiwinnetou commented Jul 21, 2017

The reason is that, this constructor does not take isolate and we cannot pass it to it:

String::Value::Value(v8::Local<v8::Value> obj) : str_(NULL), length_(0) {
  if (obj.IsEmpty()) return;
  i::Isolate* isolate = i::Isolate::Current();
  Isolate* v8_isolate = reinterpret_cast<Isolate*>(isolate);
  ENTER_V8(isolate);
  i::HandleScope scope(isolate);
  Local<Context> context = v8_isolate->GetCurrentContext();
  TryCatch try_catch(v8_isolate);
  Local<String> str;
  if (!obj->ToString(context).ToLocal(&str)) return;
  length_ = str->Length();
  str_ = i::NewArray<uint16_t>(length_ + 1);
  str->Write(str_);
}

I have been trying to create a new constructor (overloaded that takes Isolate and uses it instead of this broken ThreadLocals that get desynchronized over time.

Due to my rusty C++ knowledge I cannot do this, not to mention that this will require patching V8, which is not ideal...

The actual issue is in this line:

i::Isolate* isolate = i::Isolate::Current();

so over time due to some race conditions or whatever(I don't know), I think this gets desynchronized with isolate defined in V8

@irbull
Copy link
Member

irbull commented Jul 21, 2017

So is that a V8 thing? Do you think there is a workaround we can use in J2V8?

@matiwinnetou
Copy link
Contributor Author

That is a very good question, it could be a bug in V8 itself or our misuse of it. Generally those ThreadLocals and i::Isolate::Current(); are evil but I really don't know how to fix this elegantly I was hoping you may know.

@irbull
Copy link
Member

irbull commented Jul 21, 2017

I'll take a look. Still getting out of vacation mode :). Also, every time I venture back in to the .cpp files, I have to relearn the V8 API.

@matiwinnetou
Copy link
Contributor Author

IMHO, merging my PRs won't hurt but it doesn't fix the situation 100%

@matiwinnetou
Copy link
Contributor Author

I also looked in master of V8, latest, latest, there are still comments about removal and deprecation of:
i::Isolate::Current();

  // TODO(jochen): Once we got rid of Isolate::Current(), we can remove this.
  Isolate::Scope isolate_scope(v8_isolate);
  if (params.entry_hook || !i::Snapshot::Initialize(isolate)) {
    isolate->Init(NULL);
  }

@matiwinnetou
Copy link
Contributor Author

They are basically storing Isolate in ThreadLocals. From isolate.h:

  static void SetIsolateThreadLocals(Isolate* isolate,
                                     PerIsolateThreadData* data);

  // Find the PerThread for this particular (isolate, thread) combination.
  // If one does not yet exist, allocate a new one.
  PerIsolateThreadData* FindOrAllocatePerThreadDataForThisThread();

  // Initializes the current thread to run this Isolate.
  // Not thread-safe. Multiple threads should not Enter/Exit the same isolate
  // at the same time, this should be prevented using external locking.
  void Enter();

  // Exits the current thread. The previosuly entered Isolate is restored
  // for the thread.
  // Not thread-safe. Multiple threads should not Enter/Exit the same isolate
  // at the same time, this should be prevented using external locking.
  void Exit();

  void InitializeThreadLocal();

@irbull
Copy link
Member

irbull commented Jul 21, 2017

I agree. This is great work! I will get these PRs merged and then look through any other uses we have (I guess you didn't see any other places we explicitly use Issolage::Current()). At least we know what the problem is.

@matiwinnetou
Copy link
Contributor Author

matiwinnetou commented Jul 21, 2017

@irbull yes, two heads are better than one, I did some ground work this week to understand better the nature of the problem. What I still have no idea is why those ThreadLocals get desynchronized so that Isolate both pointers the one in C++ later V8 and those ThreadLocals in V8 code get desynced.

There are a few schools of thought how to continue further IMHO:

  1. Find out why Isolates get desychronized and fix the problem. I failed here so far.
  2. Patch V8 in such a way that actually refactoring is performed to remove i::Isolate::Current();, as they want this anyway, see their TODO entry above. Once refactoring is done, submit PR to V8 codebase. Replace all places where Isolate is retrieved via static method and usage of ThreadLocals with explicitly passing Isolate (tedious code and really verbose but way less brittle I think).
    ....
  3. The last school of thought is the most radical possible I can imagine so a bit out I guess now, try out J2V8 as another project, e.g. with Mozilla SpiderMonkey instead of Google V8. They may have more elegant implementation and as I read recently equally performant now as before. Needless to say this is massive amount of work and probably too early for such radical step.

Copy link
Member

@irbull irbull left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1

@irbull irbull merged commit ad69c4b into eclipsesource:master Jul 21, 2017
@matiwinnetou matiwinnetou deleted the issue-309 branch July 21, 2017 22:01
@matiwinnetou
Copy link
Contributor Author

matiwinnetou commented Jul 21, 2017

Thank you for merging PR.

If you do not mind I will create a new issue about an unsolved crash and copy there investigation notes and our conversation as a log to document it.

String::Value::Value(v8::Local<v8::Value> obj) : str_(NULL), length_(0) {
  if (obj.IsEmpty()) return;
  i::Isolate* isolate = i::Isolate::Current();
  Isolate* v8_isolate = reinterpret_cast<Isolate*>(isolate);
  ENTER_V8(isolate);
  i::HandleScope scope(isolate);
  Local<Context> context = v8_isolate->GetCurrentContext();
  TryCatch try_catch(v8_isolate);
  Local<String> str;
  if (!obj->ToString(context).ToLocal(&str)) return;
  length_ = str->Length();
  str_ = i::NewArray<uint16_t>(length_ + 1);
  str->Write(str_);
}

@irbull
Copy link
Member

irbull commented Jul 21, 2017

That would be great!

@matiwinnetou
Copy link
Contributor Author

Done #313

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Threading issue -> getting isolate via static calls returns NULL
2 participants