diff --git a/doc/api/addons.markdown b/doc/api/addons.markdown index 1f0562ede2c938..0609084e1a9fd5 100644 --- a/doc/api/addons.markdown +++ b/doc/api/addons.markdown @@ -811,3 +811,71 @@ Test it with: var result = addon.add(obj1, obj2); console.log(result); // 30 + +### AtExit hooks +#### void AtExit(callback, args) + +* `callback`: `void (*)(void*)` - A pointer to the function to call at exit. +* `args`: `void*` - A pointer to pass to the callback at exit. + +Registers exit hooks that run after the event loop has ended, but before the VM +is killed. + +Callbacks are run in last-in, first-out order. AtExit takes two parameters: +a pointer to a callback function to run at exit, and a pointer to untyped +context data to be passed to that callback. + +The file `addon.cc` implements AtExit below: + + // addon.cc + #undef NDEBUG + #include + #include + #include + + namespace demo { + + using node::AtExit; + using v8::HandleScope; + using v8::Isolate; + using v8::Local; + using v8::Object; + + static char cookie[] = "yum yum"; + static int at_exit_cb1_called = 0; + static int at_exit_cb2_called = 0; + + static void at_exit_cb1(void* arg) { + Isolate* isolate = static_cast(arg); + HandleScope scope(isolate); + Local obj = Object::New(isolate); + assert(!obj.IsEmpty()); // assert VM is still alive + assert(obj->IsObject()); + at_exit_cb1_called++; + } + + static void at_exit_cb2(void* arg) { + assert(arg == static_cast(cookie)); + at_exit_cb2_called++; + } + + static void sanity_check(void*) { + assert(at_exit_cb1_called == 1); + assert(at_exit_cb2_called == 2); + } + + void init(Local exports) { + AtExit(sanity_check); + AtExit(at_exit_cb2, cookie); + AtExit(at_exit_cb2, cookie); + AtExit(at_exit_cb1, exports->GetIsolate()); + } + + NODE_MODULE(addon, init); + + } // namespace demo + +Test in JavaScript by running: + + // test.js + var addon = require('./build/Release/addon');