From 6a3e9d91f90549356147b6fc7853dd3ecae8eb8b Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Wed, 6 Nov 2024 21:28:36 +1030 Subject: [PATCH] libplugin: insist on always having a non-NULL command context. And remove command_done() which was used when there was no cmd. Signed-off-by: Rusty Russell --- plugins/autoclean.c | 6 +-- plugins/libplugin.c | 24 ++++------- plugins/libplugin.h | 67 +++++++++++++++++++------------ plugins/test/run-route-calc.c | 18 ++++++--- plugins/test/run-route-overlong.c | 18 ++++++--- 5 files changed, 76 insertions(+), 57 deletions(-) diff --git a/plugins/autoclean.c b/plugins/autoclean.c index 83c896db8..5e560efe2 100644 --- a/plugins/autoclean.c +++ b/plugins/autoclean.c @@ -509,7 +509,7 @@ static struct command_result *list_done(struct command *cmd, } subsystem->cinfo->cleanup_reqs_remaining++; - req = jsonrpc_request_start(plugin, NULL, ops->del_command, + req = jsonrpc_request_start(plugin, cmd, ops->del_command, del_done, del_failed, variant); ops->add_del_fields(req, buf, t); send_outreq(plugin, req); @@ -572,7 +572,7 @@ static struct command_result *do_clean(struct clean_info *cinfo) } if (cinfo->cleanup_reqs_remaining) - return command_still_pending(NULL); + return command_still_pending(cinfo->cmd); return clean_finished(cinfo); } @@ -628,7 +628,7 @@ static struct command_result *start_clean(struct clean_info *cinfo) } ps->offset = 0; - req = jsonrpc_request_start(plugin, NULL, + req = jsonrpc_request_start(plugin, cinfo->cmd, "wait", wait_done, wait_failed, ps); json_add_string(req->js, "subsystem", ops->system_name); diff --git a/plugins/libplugin.c b/plugins/libplugin.c index 20f0ecdec..dcd9c9ff1 100644 --- a/plugins/libplugin.c +++ b/plugins/libplugin.c @@ -164,11 +164,6 @@ struct command_result *command_param_failed(void) return &complete; } -struct command_result *command_done(void) -{ - return &complete; -} - struct json_filter **command_filter_ptr(struct command *cmd) { return &cmd->filter; @@ -295,7 +290,7 @@ static struct command_result *ignore_cb(struct command *command, const jsmntok_t *result, void *arg) { - return command_done(); + return &complete; } static void disable_request_cb(struct command *cmd, struct out_req *out) @@ -308,9 +303,6 @@ static void disable_request_cb(struct command *cmd, struct out_req *out) const char *json_id_prefix(const tal_t *ctx, const struct command *cmd) { - if (!cmd) - return ""; - /* Strip quotes! */ if (strstarts(cmd->id, "\"")) { assert(strlen(cmd->id) >= 2); @@ -354,6 +346,7 @@ jsonrpc_request_start_(struct plugin *plugin, struct command *cmd, { struct out_req *out; + assert(cmd); out = tal(cmd, struct out_req); out->id = append_json_id(out, plugin, method, id_prefix); out->cmd = cmd; @@ -364,8 +357,7 @@ jsonrpc_request_start_(struct plugin *plugin, struct command *cmd, tal_add_destructor2(out, destroy_out_req, plugin); /* If command goes away, don't call callbacks! */ - if (out->cmd) - tal_add_destructor2(out->cmd, disable_request_cb, out); + tal_add_destructor2(out->cmd, disable_request_cb, out); out->js = new_json_stream(NULL, cmd, NULL); json_object_start(out->js, NULL); @@ -481,8 +473,7 @@ struct command_result *command_finished(struct command *cmd, struct command_result *WARN_UNUSED_RESULT command_still_pending(struct command *cmd) { - if (cmd) - notleak_with_children(cmd); + notleak_with_children(cmd); return &pending; } @@ -1022,8 +1013,7 @@ static void handle_rpc_reply(struct plugin *plugin, const jsmntok_t *toks) } /* Remove destructor if one existed */ - if (out->cmd) - tal_del_destructor2(out->cmd, disable_request_cb, out); + tal_del_destructor2(out->cmd, disable_request_cb, out); /* We want to free this if callback doesn't. */ tal_steal(tmpctx, out); @@ -1129,7 +1119,7 @@ static struct command_result *batch_one_success(struct command *cmd, { /* If this frees stuff (e.g. fails), just return */ if (batch->cb && batch->cb(cmd, buf, result, batch->arg) == &complete) - return command_done(); + return &complete; return batch_one_complete(cmd, batch); } @@ -1140,7 +1130,7 @@ static struct command_result *batch_one_failed(struct command *cmd, { /* If this frees stuff (e.g. fails), just return */ if (batch->errcb && batch->errcb(cmd, buf, result, batch->arg) == &complete) - return command_done(); + return &complete; return batch_one_complete(cmd, batch); } diff --git a/plugins/libplugin.h b/plugins/libplugin.h index 4a1f1be26..5d8204b32 100644 --- a/plugins/libplugin.h +++ b/plugins/libplugin.h @@ -123,7 +123,8 @@ struct out_req *jsonrpc_request_start_(struct plugin *plugin, const char *buf, const jsmntok_t *result, void *arg), - void *arg); + void *arg) + NON_NULL_ARGS(1, 2, 3, 4, 6); /* This variant has callbacks received whole obj, not "result" or * "error" members. */ @@ -202,30 +203,36 @@ struct request_batch *request_batch_new_(const tal_t *ctx, struct out_req *add_to_batch(struct command *cmd, struct request_batch *batch, - const char *cmdname); + const char *cmdname) + NON_NULL_ARGS(1, 2, 3); /* We want some commands to live after this command (possibly) * completes. This creates a new command with the same id but its own * lifetime: use aux_command_done() or tal_free() when you're done. */ -struct command *aux_command(const struct command *cmd); +struct command *aux_command(const struct command *cmd) + NON_NULL_ARGS(1); /* Runs finalcb immediately if batch is empty. */ struct command_result *batch_done(struct command *cmd, - struct request_batch *batch); + struct request_batch *batch) + NON_NULL_ARGS(1, 2); /* Helper to create a JSONRPC2 response stream with a "result" object. */ -struct json_stream *jsonrpc_stream_success(struct command *cmd); +struct json_stream *jsonrpc_stream_success(struct command *cmd) + NON_NULL_ARGS(1); /* Helper to create a JSONRPC2 response stream with an "error" object. */ struct json_stream *jsonrpc_stream_fail(struct command *cmd, int code, - const char *err); + const char *err) + NON_NULL_ARGS(1, 3); /* Helper to create a JSONRPC2 response stream with an "error" object, * to which will be added a "data" object. */ struct json_stream *jsonrpc_stream_fail_data(struct command *cmd, int code, - const char *err); + const char *err) + NON_NULL_ARGS(1, 3); /* Helper to jsonrpc_request_start() and send_outreq() to update datastore. * NULL cb means ignore, NULL errcb means plugin_error. @@ -244,7 +251,8 @@ struct command_result *jsonrpc_set_datastore_(struct plugin *plugin, const char *buf, const jsmntok_t *result, void *arg), - void *arg); + void *arg) + NON_NULL_ARGS(1, 2, 3, 4, 6); #define jsonrpc_set_datastore_string(plugin, cmd, path, str, mode, cb, errcb, arg) \ jsonrpc_set_datastore_((plugin), (cmd), (path), (str), true, (mode), \ @@ -286,7 +294,8 @@ struct command_result *jsonrpc_get_datastore_(struct plugin *plugin, struct command_result *(*binary_cb)(struct command *command, const u8 *val, void *arg), - void *arg); + void *arg) + NON_NULL_ARGS(1, 2, 3); #define jsonrpc_get_datastore_string(plugin, cmd, path, cb, arg) \ jsonrpc_get_datastore_((plugin), (cmd), (path), \ @@ -312,11 +321,13 @@ struct command_result *jsonrpc_get_datastore_(struct plugin *plugin, /* This command is finished, here's the response (the content of the * "result" or "error" field) */ WARN_UNUSED_RESULT -struct command_result *command_finished(struct command *cmd, struct json_stream *response); +struct command_result *command_finished(struct command *cmd, struct json_stream *response) + NON_NULL_ARGS(1, 2); /* Helper for a command that'll be finished in a callback. */ WARN_UNUSED_RESULT -struct command_result *command_still_pending(struct command *cmd); +struct command_result *command_still_pending(struct command *cmd) + NON_NULL_ARGS(1); /* Helper to create a zero or single-value JSON object; if @str is NULL, * object is empty. */ @@ -355,28 +366,34 @@ struct command_result *WARN_UNUSED_RESULT command_done_err(struct command *cmd, enum jsonrpc_errcode code, const char *errmsg, - const struct json_out *data); + const struct json_out *data) + NON_NULL_ARGS(1, 3); /* Send a raw error response. Useful for forwarding a previous * error after cleanup */ struct command_result *command_err_raw(struct command *cmd, - const char *json_str); + const char *json_str) + NON_NULL_ARGS(1, 2); /* This command is finished, here's the result object; @cmd cannot be NULL. */ struct command_result *WARN_UNUSED_RESULT -command_success(struct command *cmd, const struct json_out *result); +command_success(struct command *cmd, const struct json_out *result) + NON_NULL_ARGS(1, 2); /* End a hook normally (with "result": "continue") */ struct command_result *WARN_UNUSED_RESULT -command_hook_success(struct command *cmd); +command_hook_success(struct command *cmd) + NON_NULL_ARGS(1); /* End a notification handler. */ struct command_result *WARN_UNUSED_RESULT -notification_handled(struct command *cmd); +notification_handled(struct command *cmd) + NON_NULL_ARGS(1); /* End a command created with aux_command. */ struct command_result *WARN_UNUSED_RESULT -aux_command_done(struct command *cmd); +aux_command_done(struct command *cmd) + NON_NULL_ARGS(1); /** * What's the deprecation_ok state for this cmd? @@ -384,7 +401,8 @@ aux_command_done(struct command *cmd); * * Either the default, or the explicit connection override. */ -bool command_deprecated_ok_flag(const struct command *cmd); +bool command_deprecated_ok_flag(const struct command *cmd) + NON_NULL_ARGS(1); /* Helper for notification handler that will be finished in a callback. */ #define notification_handler_pending(cmd) command_still_pending(cmd) @@ -422,22 +440,21 @@ struct command_result *send_outreq(struct plugin *plugin, struct command_result *forward_error(struct command *cmd, const char *buf, const jsmntok_t *error, - void *arg); + void *arg) + NON_NULL_ARGS(1, 2, 3); /* Callback to just forward result and close request; @cmd cannot be NULL */ struct command_result *forward_result(struct command *cmd, const char *buf, const jsmntok_t *result, - void *arg); + void *arg) + NON_NULL_ARGS(1, 2, 3); /* Callback for timer where we expect a 'command_result'. All timers * must return this eventually, though they may do so via a convoluted * send_req() path. */ -struct command_result *timer_complete(struct command *cmd); - -/* Signals that we've completed a command. Useful for when - * there's no `cmd` present. Deprecated! */ -struct command_result *command_done(void); +struct command_result *timer_complete(struct command *cmd) + NON_NULL_ARGS(1); /* Access timer infrastructure to add a global timer for the plugin. * diff --git a/plugins/test/run-route-calc.c b/plugins/test/run-route-calc.c index e8b93ec7f..d2078e00d 100644 --- a/plugins/test/run-route-calc.c +++ b/plugins/test/run-route-calc.c @@ -13,7 +13,8 @@ /* AUTOGENERATED MOCKS START */ /* Generated stub for aux_command */ -struct command *aux_command(const struct command *cmd UNNEEDED) +struct command *aux_command(const struct command *cmd) + { fprintf(stderr, "aux_command called!\n"); abort(); } /* Generated stub for blinded_onion_hops */ u8 **blinded_onion_hops(const tal_t *ctx UNNEEDED, @@ -23,10 +24,12 @@ u8 **blinded_onion_hops(const tal_t *ctx UNNEEDED, const struct blinded_path *path UNNEEDED) { fprintf(stderr, "blinded_onion_hops called!\n"); abort(); } /* Generated stub for command_finished */ -struct command_result *command_finished(struct command *cmd UNNEEDED, struct json_stream *response UNNEEDED) +struct command_result *command_finished(struct command *cmd UNNEEDED, struct json_stream *response) + { fprintf(stderr, "command_finished called!\n"); abort(); } /* Generated stub for command_still_pending */ -struct command_result *command_still_pending(struct command *cmd UNNEEDED) +struct command_result *command_still_pending(struct command *cmd) + { fprintf(stderr, "command_still_pending called!\n"); abort(); } /* Generated stub for daemon_poll */ int daemon_poll(struct pollfd *fds UNNEEDED, nfds_t nfds UNNEEDED, int timeout UNNEEDED) @@ -259,15 +262,18 @@ struct out_req *jsonrpc_request_start_(struct plugin *plugin UNNEEDED, const char *buf UNNEEDED, const jsmntok_t *result UNNEEDED, void *arg) UNNEEDED, - void *arg UNNEEDED) + void *arg) + { fprintf(stderr, "jsonrpc_request_start_ called!\n"); abort(); } /* Generated stub for jsonrpc_stream_fail */ struct json_stream *jsonrpc_stream_fail(struct command *cmd UNNEEDED, int code UNNEEDED, - const char *err UNNEEDED) + const char *err) + { fprintf(stderr, "jsonrpc_stream_fail called!\n"); abort(); } /* Generated stub for jsonrpc_stream_success */ -struct json_stream *jsonrpc_stream_success(struct command *cmd UNNEEDED) +struct json_stream *jsonrpc_stream_success(struct command *cmd) + { fprintf(stderr, "jsonrpc_stream_success called!\n"); abort(); } /* Generated stub for memleak_add_helper_ */ void memleak_add_helper_(const tal_t *p UNNEEDED, void (*cb)(struct htable *memtable UNNEEDED, diff --git a/plugins/test/run-route-overlong.c b/plugins/test/run-route-overlong.c index cb3dd356d..bf2186f16 100644 --- a/plugins/test/run-route-overlong.c +++ b/plugins/test/run-route-overlong.c @@ -10,7 +10,8 @@ /* AUTOGENERATED MOCKS START */ /* Generated stub for aux_command */ -struct command *aux_command(const struct command *cmd UNNEEDED) +struct command *aux_command(const struct command *cmd) + { fprintf(stderr, "aux_command called!\n"); abort(); } /* Generated stub for blinded_onion_hops */ u8 **blinded_onion_hops(const tal_t *ctx UNNEEDED, @@ -20,10 +21,12 @@ u8 **blinded_onion_hops(const tal_t *ctx UNNEEDED, const struct blinded_path *path UNNEEDED) { fprintf(stderr, "blinded_onion_hops called!\n"); abort(); } /* Generated stub for command_finished */ -struct command_result *command_finished(struct command *cmd UNNEEDED, struct json_stream *response UNNEEDED) +struct command_result *command_finished(struct command *cmd UNNEEDED, struct json_stream *response) + { fprintf(stderr, "command_finished called!\n"); abort(); } /* Generated stub for command_still_pending */ -struct command_result *command_still_pending(struct command *cmd UNNEEDED) +struct command_result *command_still_pending(struct command *cmd) + { fprintf(stderr, "command_still_pending called!\n"); abort(); } /* Generated stub for daemon_poll */ int daemon_poll(struct pollfd *fds UNNEEDED, nfds_t nfds UNNEEDED, int timeout UNNEEDED) @@ -256,15 +259,18 @@ struct out_req *jsonrpc_request_start_(struct plugin *plugin UNNEEDED, const char *buf UNNEEDED, const jsmntok_t *result UNNEEDED, void *arg) UNNEEDED, - void *arg UNNEEDED) + void *arg) + { fprintf(stderr, "jsonrpc_request_start_ called!\n"); abort(); } /* Generated stub for jsonrpc_stream_fail */ struct json_stream *jsonrpc_stream_fail(struct command *cmd UNNEEDED, int code UNNEEDED, - const char *err UNNEEDED) + const char *err) + { fprintf(stderr, "jsonrpc_stream_fail called!\n"); abort(); } /* Generated stub for jsonrpc_stream_success */ -struct json_stream *jsonrpc_stream_success(struct command *cmd UNNEEDED) +struct json_stream *jsonrpc_stream_success(struct command *cmd) + { fprintf(stderr, "jsonrpc_stream_success called!\n"); abort(); } /* Generated stub for memleak_add_helper_ */ void memleak_add_helper_(const tal_t *p UNNEEDED, void (*cb)(struct htable *memtable UNNEEDED,