brianc/node-postgres — pull request #620 by joskuijpers (2014-07-30 12:44:46+00:00)
Title: Pool: Only call destroy on a client when it is not already being destroyed

Adds a check in the error listener on the client in the pool, to
prevent calling destroy on a client when it is already being
destroyed.
Without this check, if an error occurs during the ending of the stream, such as a timeout, the client is never removed from the pool and weird things happen. (The pool keeps trying to remove idle items, forever.)

This happened in my project when I connected to a pg-server over my home-router (so I can my server everywhere): it seems it somehow does not like idle connections. client.end() takes very long (10s+) and eventually throws an ETIMEDOUT.
If this error is not caught with `pg.on('error',cb)`, it will head to the uncaughtException handler, or just exit your application with no usable stracktrace (only net.js line number). I had a very hard time discovering this.

If however you caught it, with either uncaughtException or pg.on, the program will not exit but the pool seems to be corrupted. I can't explain it clearly because I have no real clue why it happens (it seems to have to do something with Stream.prototype.end() with the generic-pool): I just saw it when I logged the generic pool verbosely and added a ton of log messages to both pool.js and generic-pool.js.
I built this gist with the output that happens without this fix: https://gist.github.com/joskuijpers/1f9d57870eed11eca506

I should write a test but I have no idea how to do so for this case. I think it should throw some error in stream.end(), but only on the event queue, in order to make pool.destroy exit.