Hi Mike. I use v8 on a multithread env, and i guess internally v8 uses the thread memory to allocate some things, so one lesson i've got when using v8 is that you must always bind one thread to one isolate.. making that particular thread exclusive to deal with the isolate and context.
So the objects allocated in the thread local storage are there when you do something on that isolate. For now im prototyping to im using just one backend thread to a v8 isolate, but later will try to allocate more than one. I've thread multiple threads managing multiple contexts but that didnt fly, so i figured that i would need also 1 isolate for thread but didnt try this yet. But when i do, i will take care to always bind and call a specific thread, because i was burned before, trying to do something with the isolate from other threads. (and i dont think is a lock issue.. my guess is the internal use of thread-local-storage) Em quinta-feira, 20 de julho de 2017 11:31:44 UTC-3, [email protected] escreveu: > > Hi, I have been porting a spidermonkey C++ embedding to V8 and have been > having problems when executing multiple threads. > > I have followed some threads via google regarding multiple > isolates/context and use of V8::Lockers. > > At startup, I create multiple isolates each with own context (persistent). > This is context pool. > > When request comes into my server on a thread created internally, I grab > the first available isolate/context pair and execute the required script. > > If I run just 1 transaction, all works ok. If I send 2 concurrent it > crashes during custom object creation. > > The js is as follows > var reqdom = new xxDomDocument(); > if (!reqdom.LoadXML(request)) > throw "Invalid request"; > var reqroot = reqdom.Root; <-- This line generates crash. > if (!reqroot) > > I am using lockers around my V8 access (though technically I didn't think > it was necessary if multiple isolates. > > Attached crash_stack.jpg shows the crash location (this is all on Windows). > > Context* Isolate::raw_native_context() { return > context()->native_context(); } is location. > > The code to create the custom xxNode object is as follows :- > > static inline T* NewObjectInstance(UNION_INFO& uinfo) > { > T* obj = new T(); > int argc = 0; > LocalValue argv[1]; > > v8::Local<v8::Function> cons = New<v8::Function>(T::constructor); > assert(!cons.IsEmpty()); > //MaybeLocalValue jsval = cons->CallAsConstructor(uinfo._context, 0, argv); > MaybeLocal<Object> jsObj = cons->NewInstance(uinfo._context, 0, argv); > assert(!jsObj.IsEmpty()); > obj->Wrap(uinfo._isolate, jsObj.ToLocalChecked()); > > return obj; > } > > NAN_GETTER(xxDomDocument::getRoot) > { > PROP_CALLBACK_ENTER(info) > > MAKE_CALLBACK_INFO(TYPE_NAN_GETTER, info) > > CDomProps* pbag = > (CDomProps*)JS_GetObjectPrivate(_context, _self); > if (pbag && pbag->m_hdom) > { > JSObject jsNode; > xxNode* node = (void*)xxNode::NewObjectInstance<xxNode>(uinfo); > .... > } > } > > The macros on the property callback are as follows :- > > #define PROP_CALLBACK_ENTER(info)\ > Isolate* _isolate = info.GetIsolate();\ > SCOPE_ENTER(_isolate)\ > Local<Object> _self = info.Holder();\ > LocalContext _context = _isolate->GetCurrentContext();\ > ContextScope _cscope(_context);\ > CPrivData* _privdata = (CPrivData*)JS_GetContextPrivate(_context);\ > LocalValue _result = v8::Null(_isolate); > > #define PROP_CALLBACK_EXIT(info, result)\ > _escope.Escape(result);\ > info.GetReturnValue().Set(result); > > #define HANDLESCOPE_PAIR(i)\ > HandleScope _scope(i);\ > EscapableHandleScope _escope(i); > > #define LOCK_ISOLATE(_isolate)\ > V8Locker _lck(_isolate);\ > IsolateScope _isoscope(_isolate); > > #define UNLOCK_ISOLATE(_isolate)\ > V8Unlocker _unlck(_isolate); > > #define LOCK_SUSPEND(_isolate)\ > _isolate->Exit();\ > V8Unlocker _unlck(_isolate); > > #define LOCK_RESUME(_isolate)\ > _isolate->Enter(); > > #define SCOPE_ENTER(_isolate)\ > LOCK_ISOLATE(_isolate)\ > HANDLESCOPE_PAIR(_isolate) > > #define MAKE_CALLBACK_INFO(utype, info)\ > UNION_INFO uinfo;\ > uinfo.type = utype;\ > uinfo._isolate = info.GetIsolate();\ > uinfo._context = uinfo._isolate->GetCurrentContext();\ > switch (uinfo.type)\ > {\ > case TYPE_NAN_INDEX_SETTER:\ > case TYPE_NAN_SETTER:\ > break;\ > case TYPE_NAN_INDEX_GETTER:\ > case TYPE_NAN_GETTER:\ > uinfo.u.propinfo = (JSVAL_PROP_ARGS*)&info;\ > break;\ > case TYPE_NAN_METHOD:\ > uinfo.u.fninfo = (JSVAL_FN_ARGS*)&info;\ > break;\ > default:\ > break;\ > } > > typedef const Nan::PropertyCallbackInfo<v8::Value> JSVAL_PROP_ARGS; > typedef const Nan::FunctionCallbackInfo<v8::Value> JSVAL_FN_ARGS; > > ////////////////////////////////////////////////////// > // Union structure to allow pass of > // property/method arguments (see above enum) > // > typedef struct _UNION_INFO > { > INFO_TYPE type; > Isolate* _isolate; > v8::Local<v8::Context> _context; > union > { > JSVAL_PROP_ARGS* propinfo; > JSVAL_FN_ARGS* fninfo; > }u; > } > UNION_INFO; > > > Does anyone recognize this crash signature?. Any help greatly appreciated > as I have spent considerable time on this. > > Regards, > Mike McIntosh > -- -- v8-dev mailing list [email protected] http://groups.google.com/group/v8-dev --- You received this message because you are subscribed to the Google Groups "v8-dev" group. To unsubscribe from this group and stop receiving emails from it, send an email to [email protected]. For more options, visit https://groups.google.com/d/optout.
