jsonrpc: fix closed connection hadling
The spdk_jsonrpc_server_conn_remove() was just swapping last connection with that is being removed. This was fine but not for BSD queues which rely on its own address. Simple fix would be to add STAILQ_INIT and STAILQ_SWAP for queued requests but we can hit the same nasty and easy to overlook bug in future. Instead convert connection array to linked list and move around only pointers. Fixes #322 Change-Id: Ibb359d281f6164bcd17df37ba9d31ffdb46c2e0a Signed-off-by: Pawel Wodkowski <pawelx.wodkowski@intel.com> Reviewed-on: https://review.gerrithub.io/414257 Tested-by: SPDK Automated Test System <sys_sgsw@intel.com> Reviewed-by: Dariusz Stojaczyk <dariuszx.stojaczyk@intel.com> Reviewed-by: Daniel Verkamp <daniel.verkamp@intel.com> Reviewed-by: Ben Walker <benjamin.walker@intel.com>
This commit is contained in:
parent
967339f3e5
commit
01a9118d0c
@ -80,13 +80,18 @@ struct spdk_jsonrpc_server_conn {
|
||||
STAILQ_HEAD(, spdk_jsonrpc_request) send_queue;
|
||||
|
||||
struct spdk_jsonrpc_request *send_request;
|
||||
|
||||
TAILQ_ENTRY(spdk_jsonrpc_server_conn) link;
|
||||
};
|
||||
|
||||
struct spdk_jsonrpc_server {
|
||||
int sockfd;
|
||||
spdk_jsonrpc_handle_request_fn handle_request;
|
||||
struct spdk_jsonrpc_server_conn conns[SPDK_JSONRPC_MAX_CONNS];
|
||||
int num_conns;
|
||||
|
||||
TAILQ_HEAD(, spdk_jsonrpc_server_conn) free_conns;
|
||||
TAILQ_HEAD(, spdk_jsonrpc_server_conn) conns;
|
||||
|
||||
struct spdk_jsonrpc_server_conn conns_array[SPDK_JSONRPC_MAX_CONNS];
|
||||
};
|
||||
|
||||
/* jsonrpc_server_tcp */
|
||||
|
@ -40,13 +40,20 @@ spdk_jsonrpc_server_listen(int domain, int protocol,
|
||||
spdk_jsonrpc_handle_request_fn handle_request)
|
||||
{
|
||||
struct spdk_jsonrpc_server *server;
|
||||
int rc, val, flag;
|
||||
int rc, val, flag, i;
|
||||
|
||||
server = calloc(1, sizeof(struct spdk_jsonrpc_server));
|
||||
if (server == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
TAILQ_INIT(&server->free_conns);
|
||||
TAILQ_INIT(&server->conns);
|
||||
|
||||
for (i = 0; i < SPDK_JSONRPC_MAX_CONNS; i++) {
|
||||
TAILQ_INSERT_TAIL(&server->free_conns, &server->conns_array[i], link);
|
||||
}
|
||||
|
||||
server->handle_request = handle_request;
|
||||
|
||||
server->sockfd = socket(domain, SOCK_STREAM, protocol);
|
||||
@ -93,12 +100,12 @@ spdk_jsonrpc_server_listen(int domain, int protocol,
|
||||
void
|
||||
spdk_jsonrpc_server_shutdown(struct spdk_jsonrpc_server *server)
|
||||
{
|
||||
int i;
|
||||
struct spdk_jsonrpc_server_conn *conn;
|
||||
|
||||
close(server->sockfd);
|
||||
|
||||
for (i = 0; i < server->num_conns; i++) {
|
||||
close(server->conns[i].sockfd);
|
||||
TAILQ_FOREACH(conn, &server->conns, link) {
|
||||
close(conn->sockfd);
|
||||
}
|
||||
|
||||
free(server);
|
||||
@ -119,29 +126,27 @@ static void
|
||||
spdk_jsonrpc_server_conn_remove(struct spdk_jsonrpc_server_conn *conn)
|
||||
{
|
||||
struct spdk_jsonrpc_server *server = conn->server;
|
||||
int conn_idx = conn - server->conns;
|
||||
|
||||
spdk_jsonrpc_server_conn_close(conn);
|
||||
|
||||
pthread_spin_destroy(&conn->queue_lock);
|
||||
assert(STAILQ_EMPTY(&conn->send_queue));
|
||||
|
||||
/* Swap conn with the last entry in conns */
|
||||
server->conns[conn_idx] = server->conns[server->num_conns - 1];
|
||||
server->num_conns--;
|
||||
TAILQ_REMOVE(&server->conns, conn, link);
|
||||
TAILQ_INSERT_HEAD(&server->free_conns, conn, link);
|
||||
}
|
||||
|
||||
static int
|
||||
spdk_jsonrpc_server_accept(struct spdk_jsonrpc_server *server)
|
||||
{
|
||||
struct spdk_jsonrpc_server_conn *conn;
|
||||
int rc, conn_idx, flag;
|
||||
int rc, flag;
|
||||
|
||||
rc = accept(server->sockfd, NULL, NULL);
|
||||
if (rc >= 0) {
|
||||
assert(server->num_conns < SPDK_JSONRPC_MAX_CONNS);
|
||||
conn_idx = server->num_conns;
|
||||
conn = &server->conns[conn_idx];
|
||||
conn = TAILQ_FIRST(&server->free_conns);
|
||||
assert(conn != NULL);
|
||||
|
||||
conn->server = server;
|
||||
conn->sockfd = rc;
|
||||
conn->closed = false;
|
||||
@ -159,8 +164,8 @@ spdk_jsonrpc_server_accept(struct spdk_jsonrpc_server *server)
|
||||
return -1;
|
||||
}
|
||||
|
||||
server->num_conns++;
|
||||
|
||||
TAILQ_REMOVE(&server->free_conns, conn, link);
|
||||
TAILQ_INSERT_TAIL(&server->conns, conn, link);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -332,12 +337,10 @@ more:
|
||||
int
|
||||
spdk_jsonrpc_server_poll(struct spdk_jsonrpc_server *server)
|
||||
{
|
||||
int rc, i;
|
||||
struct spdk_jsonrpc_server_conn *conn;
|
||||
|
||||
for (i = 0; i < server->num_conns; i++) {
|
||||
conn = &server->conns[i];
|
||||
int rc;
|
||||
struct spdk_jsonrpc_server_conn *conn, *conn_tmp;
|
||||
|
||||
TAILQ_FOREACH_SAFE(conn, &server->conns, link, conn_tmp) {
|
||||
if (conn->closed) {
|
||||
struct spdk_jsonrpc_request *request;
|
||||
|
||||
@ -365,13 +368,11 @@ spdk_jsonrpc_server_poll(struct spdk_jsonrpc_server *server)
|
||||
}
|
||||
|
||||
/* Check listen socket */
|
||||
if (server->num_conns < SPDK_JSONRPC_MAX_CONNS) {
|
||||
if (!TAILQ_EMPTY(&server->free_conns)) {
|
||||
spdk_jsonrpc_server_accept(server);
|
||||
}
|
||||
|
||||
for (i = 0; i < server->num_conns; i++) {
|
||||
conn = &server->conns[i];
|
||||
|
||||
TAILQ_FOREACH(conn, &server->conns, link) {
|
||||
if (conn->closed) {
|
||||
continue;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user