Skip to content

async_hooks: async hook stack corruption when exception prevents AsyncResource.emitAfter being called. #16156

@akdor1154

Description

@akdor1154
  • Version: 8.2.1, 8.7
  • Platform:
  • Subsystem: async_hooks

According to async_hooks docs,

If the user's callback throws an exception, emitAfter() will automatically be called for all asyncIds on the stack if the error is handled by a domain or 'uncaughtException' handler.

However, this doesn't seem to work in practice. If I set up a simple AsyncResource to bind a function to its own execution context,

class BoundFunction extends asyncHooks.AsyncResource {
  constructor(f) {
    super('BOUND_FUNCTION');
    this.f = f;
  }

  run() {
    this.emitBefore();
    f();
    this.emitAfter();
  }
}

and use it like

const f = () => {
  throw new Error('uh ho');
};

const boundF = new BoundFunction(f);

process.nextTick( () => {
  try {
    boundF.run();
  } catch (e) {
    console.log('nothing to worry about');
  }
});

Then I get the following output from node:

$ node src/demonstration.js
nothing to worry about
Error: async hook stack has become corrupted (actual: 5, expected: 6)
 1: node::AsyncWrap::PopAsyncIds(v8::FunctionCallbackInfo<v8::Value> const&) [node]
 2: v8::internal::FunctionCallbackArguments::Call(void (*)(v8::FunctionCallbackInfo<v8::Value> const&)) [node]
 3: 0xb8f43c [node]
 4: v8::internal::Builtin_HandleApiCall(int, v8::internal::Object**, v8::internal::Isolate*) [node]
 5: 0x3aa19890463d

This happens even if I set up handlers for uncaught exceptions and rejections:

process.on('uncaughtException', (e) => { console.log('no worries'); });
process.on('unhandledRejection', (e) => { console.log('relax bro'); });

If I change BoundFunction#run to look like

run() {
  this.emitBefore();
  try {
    f();
  } finally {
    this.emitAfter();
  }
}

the error goes away. I am fine with my handler looking like that, but it's a bit confusing that the docs seem to say that it shouldn't be required.

Metadata

Metadata

Assignees

No one assigned

    Labels

    async_hooksIssues and PRs related to the async hooks subsystem.docIssues and PRs related to the documentations.

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions