static njs_int_t
njs_engine_njs_destroy(njs_engine_t *engine)
{
+ njs_int_t ret;
+
+ (void) njs_vm_call_exit_hook(engine->u.njs.vm);
+
+ for ( ;; ) {
+ ret = njs_vm_execute_pending_job(engine->u.njs.vm);
+ if (ret == NJS_OK) {
+ break;
+ }
+ }
+
njs_vm_destroy(engine->u.njs.vm);
njs_mp_destroy(engine->pool);
{
uint32_t i;
njs_ev_t *ev;
+ njs_int_t ret;
+ JSContext *cx;
njs_queue_t *events;
njs_console_t *console;
njs_262agent_t *agent;
njs_queue_link_t *link;
njs_rejected_promise_t *rejected_promise;
- qjs_call_exit_hook(engine->u.qjs.ctx);
+ (void) qjs_call_exit_hook(engine->u.qjs.ctx);
+
+ for ( ;; ) {
+ ret = JS_ExecutePendingJob(JS_GetRuntime(engine->u.qjs.ctx), &cx);
+ if (ret == 0) {
+ break;
+ }
+ }
console = JS_GetRuntimeOpaque(engine->u.qjs.rt);
ngx_engine_njs_destroy(ngx_engine_t *e, ngx_js_ctx_t *ctx,
ngx_js_loc_conf_t *conf)
{
+ njs_int_t ret;
ngx_js_event_t *event;
njs_rbtree_node_t *node;
if (ctx != NULL) {
+ ret = njs_vm_call_exit_hook(e->u.njs.vm);
+ if (ret != NJS_OK) {
+ ngx_js_log_exception(e->u.njs.vm, ctx->log, "exit hook exception");
+ }
+
+ (void) ngx_njs_execute_pending_jobs(e->u.njs.vm, ctx->log);
+
node = njs_rbtree_min(&ctx->waiting_events);
while (njs_rbtree_is_there_successor(&ctx->waiting_events, node)) {
ngx_qjs_log_exception(e, ctx->log, "exit hook exception");
}
+ (void) ngx_qjs_execute_pending_jobs(cx, ctx->log);
+
node = njs_rbtree_min(&ctx->waiting_events);
while (njs_rbtree_is_there_successor(&ctx->waiting_events, node)) {
function test(r) {
njs.on('exit', function() {
ngx.log(ngx.WARN, `exit hook: bs: \${r.variables.bytes_sent}`);
+
+ new Promise((resolve) => {resolve()})
+ .then(v => ngx.log(ngx.WARN, "exit hook promise"));
});
r.return(200, `bs: \${r.variables.bytes_sent}`);
EOF
-$t->try_run('no njs')->plan(3);
+$t->try_run('no njs')->plan(4);
###############################################################################
$t->stop();
-like($t->read_file('error.log'), qr/\[warn\].*exit hook: bs: \d+/,
- 'exit hook logged');
+my $error_log = $t->read_file('error.log');
+
+like($error_log, qr/\[warn\].*exit hook: bs: \d+/, 'exit hook logged');
+like($error_log, qr/\[warn\].*exit hook promise/, 'exit hook promise logged');
like($t->read_file('access.log'), qr/\[var:\d+ header:626172 url:\/test\]/,
'access log has bytes_sent');
NJS_EXPORT void njs_vm_opt_init(njs_vm_opt_t *options);
NJS_EXPORT njs_vm_t *njs_vm_create(njs_vm_opt_t *options);
NJS_EXPORT void njs_vm_destroy(njs_vm_t *vm);
+NJS_EXPORT njs_int_t njs_vm_call_exit_hook(njs_vm_t *vm);
NJS_EXPORT njs_int_t njs_vm_compile(njs_vm_t *vm, u_char **start, u_char *end);
NJS_EXPORT void njs_vm_set_module_loader(njs_vm_t *vm,
}
-void
-njs_vm_destroy(njs_vm_t *vm)
+njs_int_t
+njs_vm_call_exit_hook(njs_vm_t *vm)
{
if (vm->hooks[NJS_HOOK_EXIT] != NULL) {
- (void) njs_vm_call(vm, vm->hooks[NJS_HOOK_EXIT], NULL, 0);
+ return njs_vm_call(vm, vm->hooks[NJS_HOOK_EXIT], NULL, 0);
}
+ return NJS_OK;
+}
+
+
+void
+njs_vm_destroy(njs_vm_t *vm)
+{
njs_mp_destroy(vm->mem_pool);
}