On 5/7/25 3:41 PM, Martin Morgenstern via dev wrote: > Add a timing based variant of jsonrpc_recv() and jsonrpc_session_recv() > (suffixed with '_until'). > > These new functions have an additional 'deadline' parameter and will > attempt to receive JSON-RPC messages until either a complete message > is received or the deadline is reached. > > Signed-off-by: Martin Morgenstern <martin.morgenst...@cloudandheat.com> > --- > lib/jsonrpc.c | 62 +++++++++++++++++++++++++++++++++++++++++++++++++-- > lib/jsonrpc.h | 3 +++ > 2 files changed, 63 insertions(+), 2 deletions(-) > > diff --git a/lib/jsonrpc.c b/lib/jsonrpc.c > index a352e01fb..c2bd72408 100644 > --- a/lib/jsonrpc.c > +++ b/lib/jsonrpc.c > @@ -443,6 +443,54 @@ jsonrpc_recv(struct jsonrpc *rpc, struct jsonrpc_msg > **msgp) > return EAGAIN; > } > > +/* Attempts to receive a message from 'rpc' until either a complete message > + * is received or the given deadline has passed. > + * > + * If successful, stores the received message in '*msgp' and returns 0. The > + * caller takes ownership of '*msgp' and must eventually destroy it with > + * jsonrpc_msg_destroy(). > + * > + * Otherwise, stores NULL in '*msgp' and returns one of the following: > + * > + * - EAGAIN: No message has been received (e.g., if the underlying stream > + * blocks). > + * > + * - ETIME: The deadline passed and we could not receive a complete message > + * in the meantime. > + * > + * - EOF: The remote end closed the connection gracefully. > + * > + * - Otherwise an errno value that represents a JSON-RPC protocol violation > + * or another error fatal to the connection. 'rpc' will not send or > + * receive any more messages. > + */ > +int > +jsonrpc_recv_until(struct jsonrpc *rpc, struct jsonrpc_msg **msgp, > + long long deadline) > +{ > + *msgp = NULL; > + if (rpc->status) { > + return rpc->status; > + } > + > + while (time_msec() < deadline) {
We should try at least once even if we're past the deadline. So, this should be a do {} while(); loop instead. Otherwise the coverage counter below will be inaccurate and we may also get ourselves into a weird situation where we never receive anything at all. > + int retval = jsonrpc_recv_chunk(rpc); > + if (retval) { > + return retval; > + } > + retval = jsonrpc_get_message(rpc, msgp); > + if (retval != ENODATA) { > + return retval; > + } > + } > + > + /* We tried hard but didn't get a complete JSON message before the given > + * deadline. We want to know how often we abort for this reason. */ > + COVERAGE_INC(jsonrpc_recv_incomplete); > + > + return ETIME; EAGAIN should be perfectly reasonable return code here. The caller should try again. In general, reusing standard POSIX error codes for non-standard situations may be a little confusing for the users if we ever print them out. And, as mentioned in my reply ot the previous patch, this function is not really different enough from the regular one to be a separate function, IMO. > +} > + > /* Causes the poll loop to wake up when jsonrpc_recv() may return a value > other > * than EAGAIN. */ > void > @@ -1222,14 +1270,18 @@ jsonrpc_session_send(struct jsonrpc_session *s, > struct jsonrpc_msg *msg) > } > > struct jsonrpc_msg * > -jsonrpc_session_recv(struct jsonrpc_session *s) > +jsonrpc_session_recv_until(struct jsonrpc_session *s, long long deadline) > { > if (s->rpc) { > unsigned int received_bytes; > struct jsonrpc_msg *msg; > > received_bytes = jsonrpc_get_received_bytes(s->rpc); > - jsonrpc_recv(s->rpc, &msg); > + if (deadline) { > + jsonrpc_recv_until(s->rpc, &msg, deadline); > + } else { > + jsonrpc_recv(s->rpc, &msg); > + } > > long long int now = time_msec(); > reconnect_receive_attempted(s->reconnect, now); > @@ -1262,6 +1314,12 @@ jsonrpc_session_recv(struct jsonrpc_session *s) > return NULL; > } > > +struct jsonrpc_msg * > +jsonrpc_session_recv(struct jsonrpc_session *s) > +{ > + return jsonrpc_session_recv_until(s, 0); > +} > + > void > jsonrpc_session_recv_wait(struct jsonrpc_session *s) > { > diff --git a/lib/jsonrpc.h b/lib/jsonrpc.h > index 1baffcd80..09a4b0fd1 100644 > --- a/lib/jsonrpc.h > +++ b/lib/jsonrpc.h > @@ -59,6 +59,7 @@ const char *jsonrpc_get_name(const struct jsonrpc *); > > int jsonrpc_send(struct jsonrpc *, struct jsonrpc_msg *); > int jsonrpc_recv(struct jsonrpc *, struct jsonrpc_msg **); > +int jsonrpc_recv_until(struct jsonrpc *, struct jsonrpc_msg **, long long); While the structs are self-explanatory, the 'long long' is not. It should have a variable name. > void jsonrpc_recv_wait(struct jsonrpc *); > > int jsonrpc_send_block(struct jsonrpc *, struct jsonrpc_msg *); > @@ -125,6 +126,8 @@ size_t jsonrpc_session_get_n_remotes(const struct > jsonrpc_session *); > > int jsonrpc_session_send(struct jsonrpc_session *, struct jsonrpc_msg *); > struct jsonrpc_msg *jsonrpc_session_recv(struct jsonrpc_session *); > +struct jsonrpc_msg *jsonrpc_session_recv_until(struct jsonrpc_session *, > + long long); Same here. > void jsonrpc_session_recv_wait(struct jsonrpc_session *); > > bool jsonrpc_session_is_alive(const struct jsonrpc_session *); _______________________________________________ dev mailing list d...@openvswitch.org https://mail.openvswitch.org/mailman/listinfo/ovs-dev