Here's an incremental. --- lib/unixctl.c | 76 +++++++++++++++++++++-------------------------- lib/vlog.c | 2 +- utilities/ovs-appctl.c | 3 +- 3 files changed, 36 insertions(+), 45 deletions(-)
diff --git a/lib/unixctl.c b/lib/unixctl.c index c68b059..054ce49 100644 --- a/lib/unixctl.c +++ b/lib/unixctl.c @@ -48,10 +48,8 @@ struct unixctl_conn { struct jsonrpc *rpc; /* Only one request can be in progress at a time. While the request is - * being processed, 'request_id' is populated. Once a reply is ready - * 'reply' is populated. Once the reply is sent, both are NULL. */ + * being processed, 'request_id' is populated, otherwise it is null. */ struct json *request_id; /* ID of the currently active request. */ - struct jsonrpc_msg *reply; /* Reply to the currently active request. */ }; /* Server for control connection. */ @@ -132,10 +130,10 @@ unixctl_command_reply__(struct unixctl_conn *conn, bool success, const char *body) { struct json *body_json; + struct jsonrpc_msg *reply; COVERAGE_INC(unixctl_replied); assert(conn->request_id); - assert(!conn->reply); if (!body) { body = ""; @@ -148,14 +146,22 @@ unixctl_command_reply__(struct unixctl_conn *conn, } if (success) { - conn->reply = jsonrpc_create_reply(body_json, conn->request_id); + reply = jsonrpc_create_reply(body_json, conn->request_id); } else { - conn->reply = jsonrpc_create_error(body_json, conn->request_id); + reply = jsonrpc_create_error(body_json, conn->request_id); } + + /* If jsonrpc_send() returns an error, the run loop will take care of the + * problem eventually. */ + jsonrpc_send(conn->rpc, reply); + json_destroy(conn->request_id); + conn->request_id = NULL; } /* Replies to the active unixctl connection 'conn'. 'result' is sent to the - * client indicating the command was processed successfully. */ + * client indicating the command was processed successfully. Only one call to + * unixctl_command_reply() or unixctl_command_reply_error() may be made per + * request. */ void unixctl_command_reply(struct unixctl_conn *conn, const char *result) { @@ -163,7 +169,9 @@ unixctl_command_reply(struct unixctl_conn *conn, const char *result) } /* Replies to the active unixctl connection 'conn'. 'error' is sent to the - * client indicating an error occured processing the command. */ + * client indicating an error occured processing the command. Only one call to + * unixctl_command_reply() or unixctl_command_reply_error() may be made per + * request. */ void unixctl_command_reply_error(struct unixctl_conn *conn, const char *error) { @@ -285,47 +293,35 @@ process_command(struct unixctl_conn *conn, struct jsonrpc_msg *request) static int run_connection(struct unixctl_conn *conn) { - bool event; - int error; + int error, i; jsonrpc_run(conn->rpc); error = jsonrpc_get_status(conn->rpc); - if (error) { + if (error || jsonrpc_get_backlog(conn->rpc)) { return error; } - do { - event = false; - - if (conn->reply) { - event = true; - - error = jsonrpc_send(conn->rpc, conn->reply); - conn->reply = NULL; + for (i = 0; i < 10; i++) { + struct jsonrpc_msg *msg; - json_destroy(conn->request_id); - conn->request_id = NULL; + if (error || conn->request_id) { + break; } - if (!error && !conn->request_id) { - struct jsonrpc_msg *msg; - - error = jsonrpc_recv(conn->rpc, &msg); - if (msg) { - event = true; - - if (msg->type == JSONRPC_REQUEST) { - process_command(conn, msg); - } else { - VLOG_WARN_RL(&rl, "%s: received unexpected %s message", - jsonrpc_get_name(conn->rpc), - jsonrpc_msg_type_to_string(msg->type)); - error = EINVAL; - } - jsonrpc_msg_destroy(msg); + jsonrpc_recv(conn->rpc, &msg); + if (msg) { + if (msg->type == JSONRPC_REQUEST) { + process_command(conn, msg); + } else { + VLOG_WARN_RL(&rl, "%s: received unexpected %s message", + jsonrpc_get_name(conn->rpc), + jsonrpc_msg_type_to_string(msg->type)); + error = EINVAL; } + jsonrpc_msg_destroy(msg); } - } while (!error && event); + error = error ? error : jsonrpc_get_status(conn->rpc); + } return error; } @@ -336,7 +332,6 @@ kill_connection(struct unixctl_conn *conn) list_remove(&conn->node); jsonrpc_close(conn->rpc); json_destroy(conn->request_id); - jsonrpc_msg_destroy(conn->reply); free(conn); } @@ -391,9 +386,6 @@ unixctl_server_wait(struct unixctl_server *server) if (!jsonrpc_get_backlog(conn->rpc)) { jsonrpc_recv_wait(conn->rpc); } - if (conn->reply) { - poll_immediate_wake(); - } } } diff --git a/lib/vlog.c b/lib/vlog.c index 87ef4eb..4c97ef4 100644 --- a/lib/vlog.c +++ b/lib/vlog.c @@ -452,7 +452,7 @@ vlog_unixctl_list(struct unixctl_conn *conn, int argc OVS_UNUSED, const char *argv[] OVS_UNUSED, void *aux OVS_UNUSED) { char *msg = vlog_get_levels(); - unixctl_command_reply(conn, msg); + unixctl_command_reply(conn, msg); free(msg); } diff --git a/utilities/ovs-appctl.c b/utilities/ovs-appctl.c index 19acb94..241b6c0 100644 --- a/utilities/ovs-appctl.c +++ b/utilities/ovs-appctl.c @@ -69,8 +69,7 @@ main(int argc, char *argv[]) } else if (cmd_result) { fputs(cmd_result, stdout); } else { - ovs_error(0, "%s: server did not return a result or an error", target); - exit(2); + NOT_REACHED(); } jsonrpc_close(client); -- 1.7.9.1 _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev