|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [PATCH v8 01/10] error: auto propagated local_err
On 3/5/20 11:15 PM, Vladimir Sementsov-Ogievskiy wrote: Here is introduced ERRP_AUTO_PROPAGATE macro, to be used at start of functions with an errp OUT parameter. As an aid to writing imperative-style commit messages, I like to prepend an implicit "Apply this patch to..." before the user's text, to see if things still make sense. By that construct, this paragraph might read better as: Introduce a new ERRP_AUTO_PROPAGATE macro, ... It has three goals: 1. Fix issue with error_fatal and error_prepend/error_append_hint: user can't see this additional information, because exit() happens in error_setg earlier than information is added. [Reported by Greg Kurz] 2. Fix issue with error_abort and error_propagate: when we wrap error_abort by local_err+error_propagate, the resulting coredump will refer to error_propagate and not to the place where error happened. (the macro itself doesn't fix the issue, but it allows us to [3.] drop the local_err+error_propagate pattern, which will definitely fix the issue) [Reported by Kevin Wolf] 3. Drop local_err+error_propagate pattern, which is used to workaround void functions with errp parameter, when caller wants to know resulting status. (Note: actually these functions could be merely updated to return int error code). To achieve these goals, later patches will add invocations of this macro at the start of functions with either use error_prepend/error_append_hint (solving 1) or which use local_err+error_propagate to check errors, switching those functions to use *errp instead (solving 2 and 3). Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@xxxxxxxxxxxxx> --- I have lots of grammar suggestions for the comments (and I know Markus is generally okay doing wording tweaks, so it may still end up different than my suggestions): +++ b/include/qapi/error.h @@ -15,6 +15,8 @@ /* * Error reporting system loosely patterned after Glib's GError. * + * = Deal with Error object = + * * Create an error: * error_setg(&err, "situation normal, all fouled up"); * @@ -47,28 +49,88 @@ * reporting it (primarily useful in testsuites): * error_free_or_abort(&err); * - * Pass an existing error to the caller: - * error_propagate(errp, err); - * where Error **errp is a parameter, by convention the last one. + * = Deal with Error ** function parameter = * - * Pass an existing error to the caller with the message modified: - * error_propagate_prepend(errp, err); + * Function may use error system to return errors. In this case function + * defines Error **errp parameter, which should be the last one (except for + * functions which varidic argument list), which has the following API: A function may use the error system to return errors. In this case, the function defines an Error **errp parameter, by convention the last one (with exceptions for functions using ... or va_list). * - * Avoid - * error_propagate(errp, err); - * error_prepend(errp, "Could not frobnicate '%s': ", name); - * because this fails to prepend when @errp is &error_fatal. + * Caller may pass as errp: The caller may then pass in the following errp values: + * 1. &error_abort + * This means abort on any error Any error will result in abort() + * 2. &error_fatal + * Exit with non-zero return code on error Any error will result in exit() with a non-zero status + * 3. NULL + * Ignore errors Any error will be ignored + * 4. Another value 4. The address of a NULL-initialized Error *err + * On error allocate error object and set errp Any error will populate errp with an error object * - * Create a new error and pass it to the caller: - * error_setg(errp, "situation normal, all fouled up"); + * Error API functions with Error ** (like error_setg) argument supports these + * rules, so user functions just need to use them appropriately (read below). The following rules then implement the correct semantics desired by the caller. * - * Call a function and receive an error from it: + * Simple pass error to the caller: Create a new error to pass to the caller: + * error_setg(errp, "Some error"); You lost the fun wording in Markus' earlier example ("situation normal, all fouled up"). + * + * Subcall of another errp-based function, passing the error to the caller + * f(..., errp); Calling another errp-based function: + * + * == Checking success of subcall == + * + * If function returns error code in addition to errp (which is recommended), If a function returns a value indicating an error in addition to setting errp (which is recommended), then If a function returns nothing (not recommended for new code), the only way to check success is by consulting errp; doing this safely requires the use of the ERRP_AUTO_PROPAGATE macro, like this: do we want ERRNO capitalized here? + * } + * ... + * } + * + * ERRP_AUTO_PROPAGATE cares about Error ** API, wraps original errp if needed, + * so that it can be safely used (including dereferencing), and auto-propagates + * error to original errp on function end. ERRP_AUTO_PROPAGATE takes care of wrapping the original errp as needed, so that the rest of the function can directly use errp (including dereferencing), where any errors will then be propagated on to the original errp when leaving the function. Hmm - if we bulk-convert the entire tree, then there won't be any deprecated uses to be worth documenting. But if we do keep this paragraph: Note that older code that did not use ERRP_AUTO_PROPAGATE would instead need a local Err variable and the use of error_propagate() to properly handle all possible caller values of errp. + * + * Note also, that if you want to use error_append_hint/error_prepend or their + * variants, you must use ERRP_AUTO_PROPAGATE too. Otherwise, in case of + * error_fatal, you'll miss the chance to insert your additional information + * into Error object. Note that any function that wants to modify an error object, such as by calling error_append_hint or error_prepend, must use ERRP_AUTO_PROPAGATE, in order for a caller's use of &error_fatal to see the additional information. Again, I'm not sure we need this section in the codebase if we do a bulk conversion. But moving it to the commit message is still useful. + * The following pattern of receiving checking and passing the caller of the + * error by hand is deprecated now: The following pattern of receiving, checking, and then forwarding an error to the caller by hand is now deprecated: Drop "(defined below)". Again, I'm thinking the above example is more useful in the commit message instead of permanently in the .h file. */#ifndef ERROR_H This macro exists to assist with proper error handling in a function which uses an Error **errp parameter. It must be used as the first line of a function which modifies an error (with error_prepend, error_append_hint, or similar) or which wants to dereference *errp. It is still safe (but useless) to use in other functions. The macro itself looks correct. I'll leave it up to Markus how to handle the comment text, but you can add: Reviewed-by: Eric Blake <eblake@xxxxxxxxxx> -- Eric Blake, Principal Software Engineer Red Hat, Inc. +1-919-301-3226 Virtualization: qemu.org | libvirt.org _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxxxxxxxxx https://lists.xenproject.org/mailman/listinfo/xen-devel
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |