From 979b784be21d901c13824665bb8b32889190ab62 Mon Sep 17 00:00:00 2001 From: Eric Blake Date: Wed, 20 Jul 2011 17:07:59 -0600 Subject: [PATCH] error: preserve errno when saving last error It is common to see the sequence: virErrorPtr save_err = virSaveLastError(); // do cleanup virSetError(save_err); virFreeError(save_err); on cleanup paths. But for functions where it is desirable to return the errno that caused failure, this sequence can clobber that errno. virFreeError was already safe; this makes the other two functions in the sequence safe as well, assuming all goes well (on OOM, errno will be clobbered, but then again, save_err won't reflect the real error that happened, so you are no longer preserving the real situation - that's life with OOM). * src/util/virterror.c (virSaveLastError, virSetError): Preserve errno. --- src/util/virterror.c | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/src/util/virterror.c b/src/util/virterror.c index 0c7698aa25..07f8b45c47 100644 --- a/src/util/virterror.c +++ b/src/util/virterror.c @@ -295,18 +295,24 @@ virGetLastError(void) * Can be used to re-set an old error, which may have been squashed by * other functions (like cleanup routines). * - * Returns 0 on success, 1 on failure + * Returns 0 on success, -1 on failure. Leaves errno unchanged. */ int virSetError(virErrorPtr newerr) { virErrorPtr err; + int saved_errno = errno; + int ret = -1; + err = virLastErrorObject(); if (!err) - return -1; + goto cleanup; virResetError(err); - return virCopyError(newerr, err); + ret = virCopyError(newerr, err); +cleanup: + errno = saved_errno; + return ret; } /** @@ -339,7 +345,8 @@ virCopyLastError(virErrorPtr to) /** * virSaveLastError: * - * Save the last error into a new error object. + * Save the last error into a new error object. On success, errno is + * unchanged; on failure, errno is ENOMEM. * * Returns a pointer to the copied error or NULL if allocation failed. * It is the caller's responsibility to free the error with @@ -349,11 +356,13 @@ virErrorPtr virSaveLastError(void) { virErrorPtr to; + int saved_errno = errno; if (VIR_ALLOC(to) < 0) return NULL; virCopyLastError(to); + errno = saved_errno; return to; }