On Fri, Nov 17, 2017 at 7:25 AM, Jean-Marc Le Roux <jeanmarc.ler...@aerys.in > wrote:
> My assumption is that my test app terminates before the GC has a chance to > run. > To test this: > > - I run node with the --expose-gc option > - I call global.gc() at the end of my test app > > In this case, the destructor of my ObjectWrap is indeed called. > > *So it seams the GC doesn't simply "collect everything" when the app > terminates.* > *Why is that?* > > It sounds like a pretty bad things to do: some behaviors might expect the > destructor to be called in order to close a socket, etc... > because all memory is released. when the app exits. Why do extra work of minor side effects? but ya, if tf you were returning like a file to a handle and expected the close in order to flush all data out to a device it's bad... You can attach to Node::AtExit( ... ) https://nodejs.org/api/addons.html#addons_atexit_hooks which should be called so you an finalize such things. but sockets get closed by the system when a application exits also. and files are closed.... > > On Friday, November 17, 2017 at 10:27:22 AM UTC+1, Jean-Marc Le Roux wrote: >> >> Thanks for the great help! >> I think it makes a lot of sense now. >> >> So I've extended ObjectWrap like so: >> >> class BSONObject : public node::ObjectWrap >>> { >>> private: >>> bson_t* _bson; >>> public: >>> BSONObject(bson_t* bson, Local<ObjectTemplate> tpl) : >>> _bson(bson) >>> { >>> Local<Object> obj = tpl->NewInstance(); >>> initialize(v8::Isolate::GetCurrent(), obj, bson); >>> Wrap(obj); >>> } >> >> >> >> ~BSONObject() >>> { >>> std::cout << "~BSONObject()" << std::endl; >>> bson_destroy(_bson); >>> } >> >> >> >> static >>> Local<ObjectTemplate> >>> create_template(Isolate* isolate, const bson_t* document) >>> { >>> Local<ObjectTemplate> tpl = ObjectTemplate::New(isolate); >>> tpl->SetInternalFieldCount(1); >> >> >> And the "insert" function that I expose in JS and that instanciates the >> BSONObject is written like this: >> >> void >>> insert(const FunctionCallbackInfo<Value>& args) >>> { >>> Isolate* isolate = args.GetIsolate(); >>> >>> db->insert( >>> json_stringify(isolate, args[0]), >>> [&args, isolate](const bson_t* document) >>> { >>> if (!args[1]->IsUndefined()) >>> { >>> Local<Function> callback = Local<Function>::Cast(args[1]) >>> ; >>> Local<Object> obj = Object::New(isolate); >>> *Local<Value> argv[] = { (new >>> BSONObject(bson_copy(document)))->handle(isolate) };* >>> callback->Call(isolate->GetCurrentContext()->Global(), >>> 1, argv); >>> } >>> } >>> ); >>> } >> >> >> It runs fine. >> But the destructor is never called (I never see "~BSONObject()" on >> stdout). >> >> Did I miss something? >> >> Thanks ! >> >> 2017-11-16 22:01 GMT+01:00 J Decker <d3c...@gmail.com>: >> >>> You don't manage the instance, the v8 engine does. When it's no longer >>> referenced in the engine, it's garbage collected which triggers the >>> callback set when the perisstent object is made weak. >>> >>> You don't need to keep it anywhere, the object returned into the engine >>> has Internal Fields ( SetInternalFieldCount(1) ) which is used to point to >>> your native class instance. So when the callback is called, it knows what >>> to call to destruct it. >>> >>> You have to 'keep it' in the javascript scrpit if you want to keep it, >>> it's not 'kept' in the native code... >>> >>> >>> --- This is some code I've done that uses setweak directly; but it's >>> fairly scattered.... >>> >>> https://github.com/d3x0r/sack.vfs/blob/master/src/jsonParse.cc#L18 >>> >>> You can create an instance of your wrapped object with >>> >>> Local<Function> cons = Local<Function>::New( isolate, constructor ); >>> cons->NewInstance( isolate->GetCurrentContext(), argc, argv >>> ).ToLocalChecked() ; >>> >>> Hmm that's not the best example source... >>> >>> https://github.com/d3x0r/sack.vfs/blob/master/src/vfs_module.cc#L407 >>> >>> This creates a buffer, and makes it weak... >>> https://github.com/d3x0r/sack.vfs/blob/master/src/vfs_module.cc#L438 >>> >>> Local<Object> arrayBuffer = ArrayBuffer::New( isolate, buf, len ); >>> PARRAY_BUFFER_HOLDER holder = GetHolder(); >>> holder->o.Reset( isolate, arrayBuffer ); >>> holder->o.SetWeak<ARRAY_BUFFER_HOLDER>( holder, releaseBuffer, >>> WeakCallbackType::kParameter ); >>> holder->buffer = buf; >>> >>> PARRAY_BUFFER_HOLDER is just a type that holds the thing to be free (or >>> object containing things to be released), and the persistent reference that >>> has been made weak... >>> >>> struct arrayBufferHolder { >>> void *buffer; >>> Persistent<Object> o; >>> }; >>> >>> >>> >>> On Thu, Nov 16, 2017 at 9:56 AM, Jean-Marc Le Roux < >>> jeanmarc.ler...@aerys.in> wrote: >>> >>>> Node offers a C++ Clss extention ObjectWrap >>>> >>>> >>>> Thanks ! >>>> It is related to node. Yet I'm not sure how I'm supposed to use >>>> ObjectWrap. >>>> >>>> I understand I have to create my own class that extends ObjectWrap and >>>> implement a proper destructor. >>>> Then I'll instanciate that class to wrap my Local<Object>. But how do I >>>> manage such instance? >>>> If I don't keep it somewhere, it will be destructed. >>>> If I keep it around, then I'm keeping references to potentially >>>> deallocated memory. >>>> >>>> It feels like I end up with the same problem... >>>> >>>> 2017-11-16 18:36 GMT+01:00 J Decker <d3c...@gmail.com>: >>>> >>>>> >>>>> >>>>> On Thu, Nov 16, 2017 at 1:24 AM, Jean-Marc Le Roux < >>>>> jeanmarc.ler...@aerys.in> wrote: >>>>> >>>>>> I assume you're storing references to the objects as Persistent? >>>>>> >>>>>> >>>>>> Nope. You've got the whole code up there. >>>>>> So if I understand correctly: >>>>>> >>>>>> - the objects I need to keep track of the lifecycle should be >>>>>> made Persistent ; >>>>>> - all the other values can be set as Local ; >>>>>> - I should set the weak callback using MakeWeak ; >>>>>> - callback will be called when such object is GCed and I can free >>>>>> my C/C++ memory then. >>>>>> >>>>>> Is that correct ? >>>>>> >>>>> >>>>> Yes. I sthis perhaps related to Node? >>>>> Node offers a C++ Clss extention ObjectWrap >>>>> >>>>> https://nodejs.org/api/addons.html#addons_wrapping_c_objects >>>>> https://github.com/nodejs/node/blob/master/src/node_object_wrap.h >>>>> >>>>> which simplifies that whole process... when the object is GC'd the >>>>> class destructor will get called so you can release values there. >>>>> >>>>> >>>>> >>>>>> >>>>>> 2017-11-15 19:50 GMT+01:00 J Decker <d3c...@gmail.com>: >>>>>> >>>>>>> I assume you're storing references to the objects as Persistent? >>>>>>> All you need to do then is call SetWeak() https://v8docs.nodes >>>>>>> ource.com/node-0.10/d2/d78/classv8_1_1_persistent.html >>>>>>> void MakeWeak (void *parameters, WeakReferenceCallback callback) >>>>>>> >>>>>>> the callback is called when the object is GC'd. >>>>>>> >>>>>>> >>>>>>> On Wed, Nov 15, 2017 at 8:37 AM, Jean-Marc Le Roux < >>>>>>> jeanmarc.ler...@aerys.in> wrote: >>>>>>> >>>>>>>> So I've found a solution to make things lazy: I set an accessor >>>>>>>> instead of decoding/setting the actual value. >>>>>>>> >>>>>>>> void >>>>>>>> getter(Local<Name> property, const PropertyCallbackInfo<Value>& >>>>>>>> info) >>>>>>>> { >>>>>>>> Isolate* isolate = info.GetIsolate(); >>>>>>>> >>>>>>>> const bson_t* document = reinterpret_cast<bson_t*>( >>>>>>>> info.This() >>>>>>>> ->Get(String::NewFromUtf8(isolate, >>>>>>>> "__bson_document_ptr")) >>>>>>>> ->ToInt32()->Value() >>>>>>>> ); >>>>>>>> >>>>>>>> char key[255]; >>>>>>>> property->ToString(isolate)->WriteUtf8(key, 255); >>>>>>>> >>>>>>>> bson_iter_t iter; >>>>>>>> bson_iter_init(&iter, document); >>>>>>>> // FIXME: index the property so we don't have to find it >>>>>>>> bson_iter_find(&iter, key); >>>>>>>> >>>>>>>> // FIXME: replace the accessor with the deserialized value >>>>>>>> >>>>>>>> info.GetReturnValue().Set(iterator_to_value(isolate, &iter)); >>>>>>>> } >>>>>>>> >>>>>>>> Local<Value> >>>>>>>> fill_object(Isolate* isolate, Local<Object>& obj, const bson_t* >>>>>>>> document) >>>>>>>> { >>>>>>>> obj->Set( >>>>>>>> String::NewFromUtf8(isolate, "__bson_document_ptr"), >>>>>>>> Int32::New(isolate, reinterpret_cast<intptr_t>(document)) >>>>>>>> ); >>>>>>>> >>>>>>>> bson_iter_t iter; >>>>>>>> if (bson_iter_init(&iter, document)) >>>>>>>> { >>>>>>>> while (bson_iter_next(&iter)) >>>>>>>> { >>>>>>>> const char* key = bson_iter_key(&iter); >>>>>>>> >>>>>>>> if (!obj->Has(String::NewFromUtf8(isolate, >>>>>>>> key))) >>>>>>>> { >>>>>>>> obj->SetAccessor( >>>>>>>> isolate->GetCurrentContext(), >>>>>>>> String::NewFromUtf8(isolate, key), >>>>>>>> &getter >>>>>>>> ); >>>>>>>> } >>>>>>>> } >>>>>>>> } >>>>>>>> } >>>>>>>> >>>>>>>> The secret sauce is to : >>>>>>>> >>>>>>>> - keep the original data (the bson_t) allocated >>>>>>>> - store the corresponding pointer in a v8::Object >>>>>>>> >>>>>>>> But now I have a memory leak because those pointers will never be >>>>>>>> freed. >>>>>>>> How can I know when the Object will be disposed by the GC? >>>>>>>> >>>>>>>> Thanks, >>>>>>>> >>>>>>>> -- >>>>>>>> -- >>>>>>>> v8-users mailing list >>>>>>>> v8-users@googlegroups.com >>>>>>>> http://groups.google.com/group/v8-users >>>>>>>> --- >>>>>>>> You received this message because you are subscribed to the Google >>>>>>>> Groups "v8-users" group. >>>>>>>> To unsubscribe from this group and stop receiving emails from it, >>>>>>>> send an email to v8-users+unsubscr...@googlegroups.com. >>>>>>>> For more options, visit https://groups.google.com/d/optout. >>>>>>>> >>>>>>> >>>>>>> -- >>>>>>> -- >>>>>>> v8-users mailing list >>>>>>> v8-users@googlegroups.com >>>>>>> http://groups.google.com/group/v8-users >>>>>>> --- >>>>>>> You received this message because you are subscribed to a topic in >>>>>>> the Google Groups "v8-users" group. >>>>>>> To unsubscribe from this topic, visit https://groups.google.com/d/to >>>>>>> pic/v8-users/aVeevQcHJ2c/unsubscribe. >>>>>>> To unsubscribe from this group and all its topics, send an email to >>>>>>> v8-users+unsubscr...@googlegroups.com. >>>>>>> For more options, visit https://groups.google.com/d/optout. >>>>>>> >>>>>> >>>>>> >>>>>> >>>>>> -- >>>>>> *Jean-Marc Le Roux* >>>>>> >>>>>> >>>>>> Founder and CEO of Aerys (http://aerys.in) >>>>>> >>>>>> Blog: http://blogs.aerys.in/jeanmarc-leroux >>>>>> Cell: (+33)6 20 56 45 78 >>>>>> Phone: (+33)9 72 40 17 58 >>>>>> >>>>>> -- >>>>>> -- >>>>>> v8-users mailing list >>>>>> v8-users@googlegroups.com >>>>>> http://groups.google.com/group/v8-users >>>>>> --- >>>>>> You received this message because you are subscribed to the Google >>>>>> Groups "v8-users" group. >>>>>> To unsubscribe from this group and stop receiving emails from it, >>>>>> send an email to v8-users+unsubscr...@googlegroups.com. >>>>>> For more options, visit https://groups.google.com/d/optout. >>>>>> >>>>> >>>>> -- >>>>> -- >>>>> v8-users mailing list >>>>> v8-users@googlegroups.com >>>>> http://groups.google.com/group/v8-users >>>>> --- >>>>> You received this message because you are subscribed to a topic in the >>>>> Google Groups "v8-users" group. >>>>> To unsubscribe from this topic, visit https://groups.google.com/d/to >>>>> pic/v8-users/aVeevQcHJ2c/unsubscribe. >>>>> To unsubscribe from this group and all its topics, send an email to >>>>> v8-users+unsubscr...@googlegroups.com. >>>>> For more options, visit https://groups.google.com/d/optout. >>>>> >>>> >>>> >>>> >>>> -- >>>> *Jean-Marc Le Roux* >>>> >>>> >>>> Founder and CEO of Aerys (http://aerys.in) >>>> >>>> Blog: http://blogs.aerys.in/jeanmarc-leroux >>>> Cell: (+33)6 20 56 45 78 >>>> Phone: (+33)9 72 40 17 58 >>>> >>>> -- >>>> -- >>>> v8-users mailing list >>>> v8-users@googlegroups.com >>>> http://groups.google.com/group/v8-users >>>> --- >>>> You received this message because you are subscribed to the Google >>>> Groups "v8-users" group. >>>> To unsubscribe from this group and stop receiving emails from it, send >>>> an email to v8-users+unsubscr...@googlegroups.com. >>>> For more options, visit https://groups.google.com/d/optout. >>>> >>> >>> -- >>> -- >>> v8-users mailing list >>> v8-users@googlegroups.com >>> http://groups.google.com/group/v8-users >>> --- >>> You received this message because you are subscribed to a topic in the >>> Google Groups "v8-users" group. >>> To unsubscribe from this topic, visit https://groups.google.com/d/to >>> pic/v8-users/aVeevQcHJ2c/unsubscribe. >>> To unsubscribe from this group and all its topics, send an email to >>> v8-users+unsubscr...@googlegroups.com. >>> For more options, visit https://groups.google.com/d/optout. >>> >> >> >> >> -- >> *Jean-Marc Le Roux* >> >> >> Founder and CEO of Aerys (http://aerys.in) >> >> Blog: http://blogs.aerys.in/jeanmarc-leroux >> Cell: (+33)6 20 56 45 78 <+33%206%2020%2056%2045%2078> >> Phone: (+33)9 72 40 17 58 <+33%209%2072%2040%2017%2058> >> > -- > -- > v8-users mailing list > v8-users@googlegroups.com > http://groups.google.com/group/v8-users > --- > You received this message because you are subscribed to the Google Groups > "v8-users" group. > To unsubscribe from this group and stop receiving emails from it, send an > email to v8-users+unsubscr...@googlegroups.com. > For more options, visit https://groups.google.com/d/optout. > -- -- v8-users mailing list v8-users@googlegroups.com http://groups.google.com/group/v8-users --- You received this message because you are subscribed to the Google Groups "v8-users" group. To unsubscribe from this group and stop receiving emails from it, send an email to v8-users+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.