I am getting this exception when I close the pool very soon after closing a query:
Uncaught Error: Bad state: Cannot write to socket, it is closed
Stack Trace:
#0 BufferedSocket.writeBufferPart (package:sqljocky/src/buffered_socket.dart:114:7)
#1 BufferedSocket.writeBuffer (package:sqljocky/src/buffered_socket.dart:108:27)
#2 _Connection._sendBufferPart (package:sqljocky/src/connection.dart:261:31)
#3 _Connection._sendBuffer (package:sqljocky/src/connection.dart:249:29)
#4 _Connection.processHandler (package:sqljocky/src/connection.dart:289:16)
#5 ConnectionPool._closeQuery.<anonymous closure> (package:sqljocky/src/connection_pool.dart:220:29)
#6 _rootRunUnary (dart:async/zone.dart:730)
#7 _RootZone.runUnary (dart:async/zone.dart:864)
#8 _Future._propagateToListeners.handleValueCallback (dart:async/future_impl.dart:488)
#9 _Future._propagateToListeners (dart:async/future_impl.dart:571)
#10 _Future._completeWithValue (dart:async/future_impl.dart:331)
#11 _Future._asyncComplete.<anonymous closure> (dart:async/future_impl.dart:393)
#12 _asyncRunCallbackLoop (dart:async/schedule_microtask.dart:23)
#13 _asyncRunCallback (dart:async/schedule_microtask.dart:32)
#14 _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:128)
Unhandled exception:
Bad state: Cannot write to socket, it is closed
#0 _rootHandleUncaughtError.<anonymous closure>.<anonymous closure> (dart:async/zone.dart:713)
#1 _asyncRunCallbackLoop (dart:async/schedule_microtask.dart:23)
#2 _asyncRunCallback (dart:async/schedule_microtask.dart:32)
#3 _asyncRunCallback (dart:async/schedule_microtask.dart:36)
#4 _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:128)
the issue seems to be that the query close fires of a Future internally, so the close() function returns before the close is actually finished:
void _closeQuery(Query q, bool retain) {
_log.finest("Closing query: ${q.sql}");
for (var cnx in _pool) {
var preparedQuery = cnx.removePreparedQueryFromCache(q.sql);
if (preparedQuery != null) {
_waitUntilReady(cnx).then((_) {
_log.finest("Connection ready - closing query: ${q.sql}");
var handler = new _CloseStatementHandler(preparedQuery.statementHandlerId);
cnx.autoRelease = !retain;
cnx.processHandler(handler, noResponse: true);
});
}
}
}
The pool close happens immediately, it closes the socket right away. This means the query close (which is delayed till after the pool close due to the Future) fails, unable to send whatever information it needs to through the socket. I've opened a ticket to sqljocky at https://github.com/jamesots/sqljocky/issues/44 but I've received no replies, and I need a workaround if it's going to take a while to get a response.
This code has allowed me to replicate the issue 100% of the time:
Future _putMethod(RestRequest request) {
return new Future.sync(() {
mysql.ConnectionPool pool = getConnectionPool();
return pool.prepare("SELECT * FROM files").then((mysql.Query query) {
return query.execute().then((result) {
// Do something?
}).then((_) {
this._log.info("Closing");
query.close();
});
}).then((_) {
pool.close();
});
});
}