Skip to content

Fix ECONNRESET error emitted after failed connect #1230

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Mar 20, 2017

Conversation

magnushiie
Copy link
Contributor

On Windows, after a connect attempt has failed, an error event with
ECONNRESET is emitted after the real connect error is propagated to the
connect callback, because the connection is not in ending state
(connection._ending) where ECONNRESET is ignored. This change ends the
connection when connect has failed.

This fixes #746.

On Windows, after a connect attempt has failed, an error event with
ECONNRESET is emitted after the real connect error is propagated to the
connect callback, because the connection is not in ending state
(connection._ending) where ECONNRESET is ignored. This change ends the
connection when connect has failed.

This fixes brianc#746.
@magnushiie
Copy link
Contributor Author

I used the following test script to see where the error came from:

const pg = require('pg');

pg.on('error', err => {
    throw new Error(`got error from pg: ${err}`);
});
pg.connect({
    connectionString: 'postgres://postgres:wrongpassword@localhost/postgres',
    log: console.log,
}, (err, client, done) => {
    if (err) {
        console.log(`pg.connect failed: ${err}`);
        done(err);
        return;
    }
    console.log(`pg.connect succeeded`);
    done();

    pg.end();
});

and the output:

acquire client begin
dispense() clients=1 available=0 info
createResource() - creating obj - count=1 min=0 max=10 verbose
connecting new client
client connection error: { error: password authentication failed for user "postgres"
    at Connection.parseE (D:\Projects\Test\pg_econnreset\node_modules\pg\lib\connection.js:554:11)
    at Connection.parseMessage (D:\Projects\Test\pg_econnreset\node_modules\pg\lib\connection.js:381:17)
    at Socket.<anonymous> (D:\Projects\Test\pg_econnreset\node_modules\pg\lib\connection.js:117:22)
    at emitOne (events.js:96:13)
    at Socket.emit (events.js:189:7)
    at readableAddChunk (_stream_readable.js:176:18)
    at Socket.Readable.push (_stream_readable.js:134:10)
    at TCP.onread (net.js:551:20)
  name: 'error',
  length: 104,
  severity: 'FATAL',
  code: '28P01',
  detail: undefined,
  hint: undefined,
  position: undefined,
  internalPosition: undefined,
  internalQuery: undefined,
  where: undefined,
  schema: undefined,
  table: undefined,
  column: undefined,
  dataType: undefined,
  constraint: undefined,
  file: 'auth.c',
  line: '307',
  routine: 'auth_failed' }
acquire client. error: { error: password authentication failed for user "postgres"
    at Connection.parseE (D:\Projects\Test\pg_econnreset\node_modules\pg\lib\connection.js:554:11)
    at Connection.parseMessage (D:\Projects\Test\pg_econnreset\node_modules\pg\lib\connection.js:381:17)
    at Socket.<anonymous> (D:\Projects\Test\pg_econnreset\node_modules\pg\lib\connection.js:117:22)
    at emitOne (events.js:96:13)
    at Socket.emit (events.js:189:7)
    at readableAddChunk (_stream_readable.js:176:18)
    at Socket.Readable.push (_stream_readable.js:134:10)
    at TCP.onread (net.js:551:20)
  name: 'error',
  length: 104,
  severity: 'FATAL',
  code: '28P01',
  detail: undefined,
  hint: undefined,
  position: undefined,
  internalPosition: undefined,
  internalQuery: undefined,
  where: undefined,
  schema: undefined,
  table: undefined,
  column: undefined,
  dataType: undefined,
  constraint: undefined,
  file: 'auth.c',
  line: '307',
  routine: 'auth_failed' }
pg.connect failed: error: password authentication failed for user "postgres"
dispense() clients=0 available=0 info
connected client error: { Error: read ECONNRESET
    at exports._errnoException (util.js:1023:11)
    at TCP.onread (net.js:572:26) code: 'ECONNRESET', errno: 'ECONNRESET', syscall: 'read' }
D:\Projects\Test\pg_econnreset\testpg.js:4
    throw new Error(`got error from pg: ${err}`);
    ^

Error: got error from pg: Error: read ECONNRESET
    at PG.pg.on.err (D:\Projects\Test\pg_econnreset\testpg.js:4:11)
    at emitTwo (events.js:106:13)
    at PG.emit (events.js:192:7)
    at PG.<anonymous> (D:\Projects\Test\pg_econnreset\node_modules\pg\lib\index.js:74:12)
    at emitOne (events.js:96:13)
    at BoundPool.emit (events.js:189:7)
    at BoundPool.<anonymous> (D:\Projects\Test\pg_econnreset\node_modules\pg-pool\index.js:65:10)
    at emitOne (events.js:96:13)
    at Client.emit (events.js:189:7)
    at Connection.<anonymous> (D:\Projects\Test\pg_econnreset\node_modules\pg\lib\client.js:183:19)

The last frame (client.js:183) is called by connection error event handler (connection.js:71), and there self._ending is false at the time, so it's not ignoring the ECONNRESET error.

@brianc
Copy link
Owner

brianc commented Mar 6, 2017

Hey @magnushiie - thank you so much for putting this together! Is there any way you could include a test for this? To write a test just add a new file under this folder that has the issue number (1230) - the file should exit with a 0 status code to indicate the tests pass. This way we can be sure not to introduce regressions in the future!

@magnushiie
Copy link
Contributor Author

Actually, the test "raises error if cannot connect" in test/integration/client/api-tests.js already fails for me without this fix:

D:\PublicSrc\node-postgres>node test\integration\client\api-tests.js
api-tests.js........Message: read ECONNRESET
Error: read ECONNRESET
    at exports._errnoException (util.js:1023:11)
    at TCP.onread (net.js:572:26)

 Error: read ECONNRESET
    at exports._errnoException (util.js:1023:11)
    at TCP.onread (net.js:572:26)```

With the fix:

D:\PublicSrc\node-postgres>node test\integration\client\api-tests.js
api-tests.js..........

When it fails, it also fails the suite (when run via make):

xargs: node: exited with status 255; aborting
make: *** [Makefile:52: test-integration] Error 124
error Command failed with exit code 2.

@brianc
Copy link
Owner

brianc commented Mar 20, 2017

Ah nice thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Unhandled 'error' event thrown when the connection password doesn't match
2 participants