/* This part is common between struct task and struct tasklet so that tasks
* can be used as-is as tasklets.
+ *
+ * Note that the process() function must ALWAYS return the task/tasklet's
+ * pointer if the task/tasklet remains valid, and return NULL if it has been
+ * deleted. The scheduler relies on this to know if it should update its state
+ * on return.
*/
#define TASK_COMMON \
struct { \
* the connection (testing !ret is enough, if fcgi_process() wasn't
* called then ret will be 0 anyway.
*/
+ if (ret < 0)
+ t = NULL;
+
if (!ret && conn_in_list) {
struct server *srv = objt_server(conn->target);
ebmb_insert(&srv->per_thr[tid].idle_conns, &conn->hash_node->node, sizeof(conn->hash_node->hash));
HA_SPIN_UNLOCK(IDLE_CONNS_LOCK, &idle_conns[tid].idle_conns_lock);
}
- return NULL;
+ return t;
}
/* callback called on any event by the connection handler.
ret |= h1_recv(h1c);
if (ret || b_data(&h1c->ibuf))
ret = h1_process(h1c);
+
/* If we were in an idle list, we want to add it back into it,
* unless h1_process() returned -1, which mean it has destroyed
* the connection (testing !ret is enough, if h1_process() wasn't
* called then ret will be 0 anyway.
*/
+ if (ret < 0)
+ t = NULL;
+
if (!ret && conn_in_list) {
struct server *srv = objt_server(conn->target);
ebmb_insert(&srv->per_thr[tid].idle_conns, &conn->hash_node->node, sizeof(conn->hash_node->hash));
HA_SPIN_UNLOCK(IDLE_CONNS_LOCK, &idle_conns[tid].idle_conns_lock);
}
- return NULL;
+ return t;
}
static void h1_reset(struct connection *conn)
*/
HA_SPIN_UNLOCK(IDLE_CONNS_LOCK, &idle_conns[tid].idle_conns_lock);
tasklet_free(tl);
+ t = NULL;
goto leave;
}
conn = h2c->conn;
* the connection (testing !ret is enough, if h2_process() wasn't
* called then ret will be 0 anyway.
*/
+ if (ret < 0)
+ t = NULL;
+
if (!ret && conn_in_list) {
struct server *srv = objt_server(conn->target);
leave:
TRACE_LEAVE(H2_EV_H2C_WAKE);
- return NULL;
+ return t;
}
/* callback called on any event by the connection handler.
if (!h2s->cs) {
h2s_destroy(h2s);
- if (h2c_is_dead(h2c))
+ if (h2c_is_dead(h2c)) {
h2_release(h2c);
+ t = NULL;
+ }
}
}
end:
TRACE_LEAVE(H2_EV_STRM_SHUT);
- return NULL;
+ return t;
}
/* shutr() called by the conn_stream (mux_ops.shutr) */
ctx->conn->subs = NULL;
} else if (ctx->cs->data_cb->wake)
ctx->cs->data_cb->wake(ctx->cs);
- return NULL;
+ return t;
}
conn_ctrl_drain(ctx->conn);
- if (ctx->conn->flags & (CO_FL_ERROR | CO_FL_SOCK_RD_SH | CO_FL_SOCK_WR_SH))
+ if (ctx->conn->flags & (CO_FL_ERROR | CO_FL_SOCK_RD_SH | CO_FL_SOCK_WR_SH)) {
mux_pt_destroy(ctx);
+ t = NULL;
+ }
else
ctx->conn->xprt->subscribe(ctx->conn, ctx->conn->xprt_ctx, SUB_RETRY_RECV,
&ctx->wait_event);
- return NULL;
+ return t;
}
/* Initialize the mux once it's attached. It is expected that conn->ctx
ebmb_insert(&srv->per_thr[tid].idle_conns, &conn->hash_node->node, sizeof(conn->hash_node->hash));
HA_SPIN_UNLOCK(IDLE_CONNS_LOCK, &idle_conns[tid].idle_conns_lock);
}
- return NULL;
+ return t;
}
/* Receive up to <count> bytes from connection <conn>'s socket and store them
int ret = 0;
if (!cs)
- return NULL;
+ return t;
if (!(si->wait_event.events & SUB_RETRY_SEND) && !channel_is_empty(si_oc(si)))
ret = si_cs_send(cs);
si_cs_process(cs);
stream_release_buffers(si_strm(si));
- return (NULL);
+ return t;
}
/* This function is designed to be called from within the stream handler to
}
tasklet_free(ctx->wait_event.tasklet);
pool_free(xprt_handshake_ctx_pool, ctx);
+ t = NULL;
}
- return NULL;
+ return t;
}
static int xprt_handshake_init(struct connection *conn, void **xprt_ctx)
qc_send_ppkts(ctx);
}
- return NULL;
+ return t;
}
/* Receive up to <count> bytes from connection <conn>'s socket and store them