Skip to content

Commit b8f0b98

Browse files
authored
Merge pull request #607 from sidorares/connect-time-errors
Fix crash when first packet from server is error packet
2 parents e8d1853 + 365b89b commit b8f0b98

File tree

2 files changed

+58
-3
lines changed

2 files changed

+58
-3
lines changed

lib/connection.js

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ function Connection(opts) {
8787

8888
this.clientEncoding = CharsetToEncoding[this.config.charsetNumber];
8989

90-
this.stream.once('error', connection._handleNetworkError.bind(this));
90+
this.stream.on('error', connection._handleNetworkError.bind(this));
9191

9292
// see https://gist.github.com/khoomeister/4985691#use-that-instead-of-bind
9393
this.packetParser = new PacketParser(function(p) {
@@ -123,11 +123,17 @@ function Connection(opts) {
123123
if (!this.config.isServer) {
124124
handshakeCommand = new Commands.ClientHandshake(this.config.clientFlags);
125125
handshakeCommand.on('end', function() {
126+
// this happens when handshake finishes early and first packet is error
127+
// and not server hello ( for example, 'Too many connactions' error)
128+
if (!handshakeCommand.handshake) {
129+
return;
130+
}
126131
connection._handshakePacket = handshakeCommand.handshake;
127132
connection.threadId = handshakeCommand.handshake.connectionId;
128133
connection.emit('connect', handshakeCommand.handshake);
129134
});
130135
handshakeCommand.on('error', function(err) {
136+
connection._closing = true;
131137
connection._notifyError(err);
132138
});
133139
this.addCommand(handshakeCommand);
@@ -212,7 +218,16 @@ Connection.prototype._notifyError = function(err) {
212218
connection._command.onResult(err);
213219
connection._command = null;
214220
} else {
215-
bubbleErrorToConnection = true;
221+
// connection handshake is special because we allow it to be implicit
222+
// if error happened during handshake, but there are others commands in queue
223+
// then bubble error to other commands and not to connection
224+
if (
225+
!(connection._command &&
226+
connection._command.constructor == Commands.ClientHandshake &&
227+
connection._commands.length > 0)
228+
) {
229+
bubbleErrorToConnection = true;
230+
}
216231
}
217232
while ((command = connection._commands.shift())) {
218233
if (command.onResult) {
@@ -791,6 +806,10 @@ Connection.prototype.destroy = function() {
791806
};
792807

793808
Connection.prototype.close = function() {
809+
if (this.connectTimeout) {
810+
Timers.clearTimeout(this.connectTimeout);
811+
this.connectTimeout = null;
812+
}
794813
this._closing = true;
795814
this.stream.end();
796815
var connection = this;
@@ -900,7 +919,7 @@ Connection.prototype.writeOk = function(args) {
900919
Connection.prototype.writeError = function(args) {
901920
// if we want to send error before initial hello was sent, use default encoding
902921
var encoding = this.serverConfig ? this.serverConfig.encoding : 'cesu8';
903-
this.writePacket(Packets.Error.toPacket(args, this.serverConfig.encoding));
922+
this.writePacket(Packets.Error.toPacket(args, encoding));
904923
};
905924

906925
Connection.prototype.serverHandshake = function serverHandshake(args) {
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
var mysql = require('../../../index.js');
2+
var assert = require('assert');
3+
var Buffer = require('safe-buffer').Buffer;
4+
5+
var server;
6+
7+
const ERROR_TEXT = 'test error';
8+
9+
var portfinder = require('portfinder');
10+
portfinder.getPort(function(err, port) {
11+
var server = mysql.createServer();
12+
server.listen(port);
13+
server.on('connection', function(conn) {
14+
console.log('Here!');
15+
conn.writeError(new Error(ERROR_TEXT));
16+
conn.close();
17+
});
18+
19+
var connection = mysql.createConnection({
20+
host: 'localhost',
21+
port: port,
22+
user: 'testuser',
23+
database: 'testdatabase',
24+
password: 'testpassword'
25+
});
26+
27+
connection.query('select 1+1', function(err) {
28+
assert.equal(err.message, ERROR_TEXT);
29+
});
30+
31+
connection.query('select 1+2', function(err) {
32+
assert.equal(err.message, ERROR_TEXT);
33+
connection.close();
34+
server._server.close();
35+
});
36+
});

0 commit comments

Comments
 (0)