Here is introduced ERRP_FUNCTION_BEGIN macro, to be used at start of functions with errp parameter.
It has three goals: 1. Fix issue with error_fatal & error_append_hint: user can't see these hints, because exit() happens in error_setg earlier than hint is appended. [Reported by Greg Kurz] 2. Fix issue with error_abort & error_propagate: when we wrap error_abort by local_err+error_propagate, 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 to [3.] drop all 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). Signed-off-by: Vladimir Sementsov-Ogievskiy <vsement...@virtuozzo.com> --- CC: John Snow <js...@redhat.com> CC: Kevin Wolf <kw...@redhat.com> CC: Max Reitz <mre...@redhat.com> CC: Fam Zheng <f...@euphon.net> CC: Jeff Cody <codypr...@gmail.com> CC: "Marc-André Lureau" <marcandre.lur...@redhat.com> CC: Paolo Bonzini <pbonz...@redhat.com> CC: Greg Kurz <gr...@kaod.org> CC: Subbaraya Sundeep <sundeep.l...@gmail.com> CC: Peter Maydell <peter.mayd...@linaro.org> CC: Paul Burton <pbur...@wavecomp.com> CC: Aleksandar Rikalo <arik...@wavecomp.com> CC: "Michael S. Tsirkin" <m...@redhat.com> CC: Marcel Apfelbaum <marcel.apfelb...@gmail.com> CC: Mark Cave-Ayland <mark.cave-ayl...@ilande.co.uk> CC: David Gibson <da...@gibson.dropbear.id.au> CC: Yuval Shaia <yuval.sh...@oracle.com> CC: Cornelia Huck <coh...@redhat.com> CC: Eric Farman <far...@linux.ibm.com> CC: Richard Henderson <r...@twiddle.net> CC: David Hildenbrand <da...@redhat.com> CC: Halil Pasic <pa...@linux.ibm.com> CC: Christian Borntraeger <borntrae...@de.ibm.com> CC: Gerd Hoffmann <kra...@redhat.com> CC: Alex Williamson <alex.william...@redhat.com> CC: Markus Armbruster <arm...@redhat.com> CC: Michael Roth <mdr...@linux.vnet.ibm.com> CC: Juan Quintela <quint...@redhat.com> CC: "Dr. David Alan Gilbert" <dgilb...@redhat.com> CC: Eric Blake <ebl...@redhat.com> CC: Jason Wang <jasow...@redhat.com> CC: "Daniel P. Berrangé" <berra...@redhat.com> CC: Eduardo Habkost <ehabk...@redhat.com> CC: qemu-block@nongnu.org CC: qemu-de...@nongnu.org CC: integrat...@gluster.org CC: qemu-...@nongnu.org CC: qemu-...@nongnu.org CC: qemu-s3...@nongnu.org include/qapi/error.h | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/include/qapi/error.h b/include/qapi/error.h index 9376f59c35..fb41f7a790 100644 --- a/include/qapi/error.h +++ b/include/qapi/error.h @@ -322,6 +322,41 @@ void error_set_internal(Error **errp, ErrorClass err_class, const char *fmt, ...) GCC_FMT_ATTR(6, 7); +typedef struct ErrorPropagator { + Error *local_err; + Error **errp; +} ErrorPropagator; + +static inline void error_propagator_cleanup(ErrorPropagator *prop) +{ + error_propagate(prop->errp, prop->local_err); +} + +G_DEFINE_AUTO_CLEANUP_CLEAR_FUNC(ErrorPropagator, error_propagator_cleanup); + +/* + * ERRP_FUNCTION_BEGIN + * + * This macro is created to be the first line of a function with Error **errp + * parameter. + * + * If errp is NULL or points to error_fatal, it is rewritten to point to a + * local Error object, which will be automatically propagated to the original + * errp on function exit (see error_propagator_cleanup). + * + * After invocation of this macro it is always safe to dereference errp + * (as it's not NULL anymore) and to append hints (by error_append_hint) + * (as, if it was error_fatal, we swapped it with a local_error to be + * propagated on cleanup). + * + * Note: we don't wrap the error_abort case, as we want resulting coredump + * to point to the place where the error happened, not to error_propagate. + */ +#define ERRP_FUNCTION_BEGIN() \ +g_auto(ErrorPropagator) __auto_errp_prop = {.errp = errp}; \ +errp = ((errp == NULL || *errp == error_fatal) ? \ + &__auto_errp_prop.local_err : errp) + /* * Special error destination to abort on error. * See error_setg() and error_propagate() for details. -- 2.21.0