lib/jsonrpc: Fix memory leaks about connection request.
There're outstanding requests in spdk_jsonrpc_parse_request which caused by connection close. There are methods to call spdk_jsonrpc_server_conn_close, including spdk_jsonrpc_server_conn_remove and spdk_jsonrpc_server_shutdown, Some rpc methods call these functions to terminate connections ,that leads to memory leaks. Try to free outstanding requests after deciding to terminate a connection. And do this follwing with close(conn->sockfd). Fix issue #784, and can resolve other similar memory leaks about this. Signed-off-by: yidong0635 <dongx.yi@intel.com> Change-Id: Icd287bd0c5670ee8ec32750b999f82b0fa89cf84 Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/458438 Tested-by: SPDK CI Jenkins <sys_sgci@intel.com> Reviewed-by: Changpeng Liu <changpeng.liu@intel.com> Reviewed-by: Darek Stojaczyk <dariusz.stojaczyk@intel.com>
This commit is contained in:
parent
6629202cbd
commit
17c006a7c3
@ -98,12 +98,39 @@ spdk_jsonrpc_server_listen(int domain, int protocol,
|
|||||||
return server;
|
return server;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static struct spdk_jsonrpc_request *
|
||||||
|
spdk_jsonrpc_server_dequeue_request(struct spdk_jsonrpc_server_conn *conn)
|
||||||
|
{
|
||||||
|
struct spdk_jsonrpc_request *request = NULL;
|
||||||
|
|
||||||
|
pthread_spin_lock(&conn->queue_lock);
|
||||||
|
request = STAILQ_FIRST(&conn->send_queue);
|
||||||
|
if (request) {
|
||||||
|
STAILQ_REMOVE_HEAD(&conn->send_queue, link);
|
||||||
|
}
|
||||||
|
pthread_spin_unlock(&conn->queue_lock);
|
||||||
|
return request;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
spdk_jsonrpc_server_free_conn_request(struct spdk_jsonrpc_server_conn *conn)
|
||||||
|
{
|
||||||
|
struct spdk_jsonrpc_request *request;
|
||||||
|
|
||||||
|
spdk_jsonrpc_free_request(conn->send_request);
|
||||||
|
conn->send_request = NULL ;
|
||||||
|
while ((request = spdk_jsonrpc_server_dequeue_request(conn)) != NULL) {
|
||||||
|
spdk_jsonrpc_free_request(request);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
spdk_jsonrpc_server_conn_close(struct spdk_jsonrpc_server_conn *conn)
|
spdk_jsonrpc_server_conn_close(struct spdk_jsonrpc_server_conn *conn)
|
||||||
{
|
{
|
||||||
conn->closed = true;
|
conn->closed = true;
|
||||||
|
|
||||||
if (conn->sockfd >= 0) {
|
if (conn->sockfd >= 0) {
|
||||||
|
spdk_jsonrpc_server_free_conn_request(conn);
|
||||||
close(conn->sockfd);
|
close(conn->sockfd);
|
||||||
conn->sockfd = -1;
|
conn->sockfd = -1;
|
||||||
|
|
||||||
@ -315,20 +342,6 @@ spdk_jsonrpc_server_send_response(struct spdk_jsonrpc_request *request)
|
|||||||
pthread_spin_unlock(&conn->queue_lock);
|
pthread_spin_unlock(&conn->queue_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct spdk_jsonrpc_request *
|
|
||||||
spdk_jsonrpc_server_dequeue_request(struct spdk_jsonrpc_server_conn *conn)
|
|
||||||
{
|
|
||||||
struct spdk_jsonrpc_request *request = NULL;
|
|
||||||
|
|
||||||
pthread_spin_lock(&conn->queue_lock);
|
|
||||||
request = STAILQ_FIRST(&conn->send_queue);
|
|
||||||
if (request) {
|
|
||||||
STAILQ_REMOVE_HEAD(&conn->send_queue, link);
|
|
||||||
}
|
|
||||||
pthread_spin_unlock(&conn->queue_lock);
|
|
||||||
return request;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
spdk_jsonrpc_server_conn_send(struct spdk_jsonrpc_server_conn *conn)
|
spdk_jsonrpc_server_conn_send(struct spdk_jsonrpc_server_conn *conn)
|
||||||
@ -392,27 +405,8 @@ spdk_jsonrpc_server_poll(struct spdk_jsonrpc_server *server)
|
|||||||
spdk_jsonrpc_server_conn_close(conn);
|
spdk_jsonrpc_server_conn_close(conn);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (conn->sockfd == -1) {
|
if (conn->sockfd == -1 && conn->outstanding_requests == 0) {
|
||||||
struct spdk_jsonrpc_request *request;
|
spdk_jsonrpc_server_conn_remove(conn);
|
||||||
|
|
||||||
/*
|
|
||||||
* The client closed the connection, but there may still be requests
|
|
||||||
* outstanding; we have no way to cancel outstanding requests, so wait until
|
|
||||||
* each outstanding request sends a response (which will be discarded, since
|
|
||||||
* the connection is closed).
|
|
||||||
*/
|
|
||||||
|
|
||||||
spdk_jsonrpc_free_request(conn->send_request);
|
|
||||||
conn->send_request = NULL;
|
|
||||||
|
|
||||||
while ((request = spdk_jsonrpc_server_dequeue_request(conn)) != NULL) {
|
|
||||||
spdk_jsonrpc_free_request(request);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (conn->outstanding_requests == 0) {
|
|
||||||
SPDK_DEBUGLOG(SPDK_LOG_RPC, "all outstanding requests completed\n");
|
|
||||||
spdk_jsonrpc_server_conn_remove(conn);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user