Skip to content

connection.close causes process to die and error is uncatchable #334

@mateodelnorte

Description

@mateodelnorte

Hi there. This is in response to a reported error in servicebus, which uses amqplib (mateodelnorte/servicebus#93).

Issue: Exiting RabbitMQ causes client code to exit without error. connection.close does fire, but subsequently throwing or emitting an error is somehow swallowed.

This behavior is showing up in servicebus, and it looks like it may be related to the promise library in amqplib. For both of the following examples (throwing uncaught error and emitting unhandled error), both applications will crash with no uncaught exception or unhandled rejection. I'd expect one of the two.

var amqp = require('amqplib');
var EventEmitter = require('events').EventEmitter;

amqp.connect('amqp://localhost').then(function (conn) {
  conn.on('close', function (event) {
    console.log('we get our event here', event)
    if (require('amqplib/lib/connection').isFatalError(event.Error)){
      console.log('and its fatal, but throwing seems to be swallowed - perhaps by the when.defer() promise?')
      throw new Error(event)
      console.log('something is catching this, eating it, and causing the process to die')
    }
  });
}).catch(function (err) {
  console.log('no error here either', err);
}).then(null, function(err) {
  console.log('no error here', err);
});

process.on('uncaughtException', function (exception) {
  console.log('no uncaught exception', exception);
});

process.on('unhandledRejection', (reason, p) => {
  console.log('no unhandled rejection at: Promise', p, 'reason:', reason);
});
class Wat extends EventEmitter {
  constructor () {
    super();

    var self = this;

    amqp.connect('amqp://localhost').then((conn) => {
      conn.on('close', function (event) {
        console.log('we get our event here', event)
        if (require('amqplib/lib/connection').isFatalError(event.Error)){
          console.log('and its fatal, but emitting error seems to be swallowed - perhaps by the when.defer() promise?')
          self.emit('error', Error(event));
          console.log('something is catching this, eating it, and causing the process to die')
        }
      });
    }).catch((err) => {
      console.log('no error here either', err);
    }).then(null, (err) => {
      console.log('no error here', err);
    });

  }
}

process.on('uncaughtException', function (exception) {
  console.log('no uncaught exception', exception);
});

process.on('unhandledRejection', (reason, p) => {
  console.log('no unhandled rejection at: Promise', p, 'reason:', reason);
});

new Wat();

Is there a particular way these errors need to be thrown/emitted/captured and re-throw/emitted?

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions