]> xenbits.xensource.com Git - libvirt.git/commitdiff
error: preserve errno when saving last error
authorEric Blake <eblake@redhat.com>
Wed, 20 Jul 2011 23:07:59 +0000 (17:07 -0600)
committerEric Blake <eblake@redhat.com>
Thu, 21 Jul 2011 13:24:33 +0000 (07:24 -0600)
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

index 0c7698aa25e5ec76f49c107eee54e14be41b5ccd..07f8b45c47605678a687ea5fbb01718404e04e00 100644 (file)
@@ -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;
 }