void *uctx; //!< User data.
void *in_handler; //!< Connection is currently in a callback.
- bool is_closed; //!< The close callback has previously been called.
bool processing_signals; //!< Processing deferred signals, don't let the deferred
///< signal processor be called multiple times.
* the FAILED state. Eventually the connection is
* shutdown, and enter_shutdown calls this function.
*/
- if (conn->close && !conn->is_closed) {
+ if (conn->close && !conn->pub.is_closed) {
HANDLER_BEGIN(conn, conn->close);
DEBUG4("Calling close(el=%p, h=%p, uctx=%p)", conn->pub.el, conn->pub.h, conn->uctx);
conn->close(conn->pub.el, conn->pub.h, conn->uctx);
- conn->is_closed = true; /* Ensure close doesn't get called twice if the connection is freed */
+ conn->pub.is_closed = true; /* Ensure close doesn't get called twice if the connection is freed */
HANDLER_END(conn);
/*
*/
if (conn->pub.state != CONNECTION_STATE_CLOSED) return;
} else {
- conn->is_closed = true;
+ conn->pub.is_closed = true;
}
WATCH_POST(conn);
}
*/
static void connection_state_enter_halted(connection_t *conn)
{
- fr_assert(conn->is_closed);
+ fr_assert(conn->pub.is_closed);
switch (conn->pub.state) {
case CONNECTION_STATE_INIT:
switch (ret) {
case CONNECTION_STATE_CONNECTING:
- conn->is_closed = false; /* We now have a handle */
+ conn->pub.is_closed = false; /* We now have a handle */
WATCH_POST(conn); /* Only call if we successfully initialised the handle */
connection_state_enter_connecting(conn);
return;
case CONNECTION_STATE_CONNECTED:
- conn->is_closed = false; /* We now have a handle */
+ conn->pub.is_closed = false; /* We now have a handle */
WATCH_POST(conn); /* Only call if we successfully initialised the handle */
connection_state_enter_connected(conn);
return;
case CONNECTION_STATE_TIMEOUT:
case CONNECTION_STATE_FAILED:
connection_state_enter_closed(conn);
- fr_assert(conn->is_closed);
+ fr_assert(conn->pub.is_closed);
FALL_THROUGH;
case CONNECTION_STATE_CLOSED:
case CONNECTION_STATE_SHUTDOWN:
case CONNECTION_STATE_TIMEOUT:
case CONNECTION_STATE_FAILED:
- if (!conn->is_closed) connection_state_enter_closed(conn);
- fr_assert(conn->is_closed);
+ if (!conn->pub.is_closed) connection_state_enter_closed(conn);
+ fr_assert(conn->pub.is_closed);
connection_state_enter_halted(conn);
break;
.pub = {
.id = id,
.state = CONNECTION_STATE_HALTED,
- .el = el
+ .el = el,
+ .is_closed = true /* Starts closed */
},
.reconnection_delay = conf->reconnection_delay,
.connection_timeout = conf->connection_timeout,
.close = funcs->close,
.failed = funcs->failed,
.shutdown = funcs->shutdown,
- .is_closed = true, /* Starts closed */
.triggers = conf->triggers,
.trigger_args = conf->trigger_args,
.trigger_cs = conf->trigger_cs,
char const *driver = inst->driver_submodule->name;
sql_log_entry_t log[20];
size_t num, i;
- TALLOC_CTX *log_ctx = talloc_new(NULL);
+ TALLOC_CTX *log_ctx;
+
+ /*
+ * Every driver reads the errors off the connection handle, which the
+ * trunk frees when it closes the connection. A query that failed
+ * because its connection died is resumed after that has happened,
+ * so there is nothing left to ask the driver for.
+ */
+ if (!query_ctx->tconn || query_ctx->tconn->conn->is_closed) {
+ ROPTIONAL(RERROR, ERROR, "%s: Connection closed", driver);
+ return;
+ }
+
+ log_ctx = talloc_new(NULL);
num = (inst->driver->sql_error)(log_ctx, log, (NUM_ELEMENTS(log)), query_ctx);
if (num == 0) {