[libvirt] [PATCH 0/2] adding virHas/GetLastErrorCode/Domain to paritally replace virGetLastError

Many places in the code call virGetLastError() just to check the raised error code, or domain. However virGetLastError() can return NULL, so the code has to check for that as well. So Instead we create functions virGetLastErrorCode and virGetLastErrorDomain (in addition to the existing virGetLastErrorMessage) that always return a valid error code/domain/message, to simplify callers. Also created virHasLastErrorCode for completion This is my first commit, for: https://wiki.libvirt.org/page/BiteSizedTasks#Add_and_use_virGetLastErrorCode... Notes: * There are a few instances of virGetLastErrorCode() left where we use multiple fields from the error, which makes sense to keep it. * I didn't manage to use virGetLastErrorDomain() (due to the above) so I'm inclined to remove it. * virHasLastError is more or less only a semantic improvement over virGetLastError, so I'm happy to revert it if needed Signed-off-by: Ramy Elkest <ramyelkest@gmail.com> ramyelkest (2): util: adding virHasLastError and virGetLastErrorCode/Domain all: replacing virGetLastError with virHas/GetLastErrorCode/Domain include/libvirt/virterror.h | 3 ++ src/libvirt_public.syms | 7 +++++ src/locking/lock_driver_lockd.c | 3 +- src/lxc/lxc_controller.c | 4 +-- src/qemu/qemu_agent.c | 3 +- src/qemu/qemu_conf.c | 3 +- src/qemu/qemu_domain.c | 2 +- src/qemu/qemu_driver.c | 12 ++++---- src/qemu/qemu_hotplug.c | 2 +- src/qemu/qemu_migration.c | 4 +-- src/qemu/qemu_monitor.c | 5 ++-- src/qemu/qemu_monitor_json.c | 2 +- src/qemu/qemu_process.c | 2 +- src/remote/remote_driver.c | 3 +- src/rpc/virnetclient.c | 2 +- src/util/virerror.c | 63 +++++++++++++++++++++++++++++++++++++++++ src/util/virfilecache.c | 3 +- src/util/virxml.c | 4 +-- tests/commandtest.c | 2 +- tests/testutils.c | 6 ++-- tests/virhostcputest.c | 2 +- tests/virstoragetest.c | 8 +++--- tools/virsh-domain-monitor.c | 7 ++--- tools/virsh-domain.c | 4 +-- tools/virsh-util.c | 3 +- tools/vsh.c | 2 +- 26 files changed, 110 insertions(+), 51 deletions(-) -- 2.7.4

Many places in the code call virGetLastError() just to check the raised error code, or domain. However virGetLastError() can return NULL, so the code has to check for that as well. So Instead we create functions virGetLastErrorCode and virGetLastErrorDomain (in addition to the existing virGetLastErrorMessage) that always return a valid error code/domain/message, to simplify callers. Also created virHasLastErrorCode for completion My first commit, for: https://wiki.libvirt.org/page/BiteSizedTasks#Add_and_use_virGetLastErrorCode... Signed-off-by: Ramy Elkest <ramyelkest@gmail.com> --- include/libvirt/virterror.h | 3 +++ src/libvirt_public.syms | 7 +++++ src/util/virerror.c | 63 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 73 insertions(+) diff --git a/include/libvirt/virterror.h b/include/libvirt/virterror.h index 3e7c7a0..8336258 100644 --- a/include/libvirt/virterror.h +++ b/include/libvirt/virterror.h @@ -344,6 +344,9 @@ void virResetLastError (void); void virResetError (virErrorPtr err); void virFreeError (virErrorPtr err); +int virHasLastError (void); +int virGetLastErrorCode (void); +int virGetLastErrorDomain (void); const char * virGetLastErrorMessage (void); virErrorPtr virConnGetLastError (virConnectPtr conn); diff --git a/src/libvirt_public.syms b/src/libvirt_public.syms index 95df3a0..3a641a3 100644 --- a/src/libvirt_public.syms +++ b/src/libvirt_public.syms @@ -785,4 +785,11 @@ LIBVIRT_4.1.0 { virStoragePoolLookupByTargetPath; } LIBVIRT_3.9.0; +LIBVIRT_4.4.0 { + global: + virHasLastError; + virGetLastErrorCode; + virGetLastErrorDomain; +} LIBVIRT_4.1.0; + # .... define new API here using predicted next version number .... diff --git a/src/util/virerror.c b/src/util/virerror.c index c000b00..818af2e 100644 --- a/src/util/virerror.c +++ b/src/util/virerror.c @@ -272,6 +272,69 @@ virGetLastError(void) /** + * virHasLastError: + * + * Check for a reported last error + * + * The error object is kept in thread local storage, so separate + * threads can safely access this concurrently. + * + * Returns 1 if there is an error and the error code is not VIR_ERR_OK, + otherwise returns 0 + */ +int +virHasLastError(void) +{ + virErrorPtr err = virLastErrorObject(); + if (!err || err->code == VIR_ERR_OK) + return 0; + return 1; +} + + +/** + * virGetLastErrorCode: + * + * Get the most recent error code + * + * The error object is kept in thread local storage, so separate + * threads can safely access this concurrently. + * + * Returns the most recent error code in this thread, + * or VIR_ERR_OK if none is set + */ +int +virGetLastErrorCode(void) +{ + virErrorPtr err = virLastErrorObject(); + if (!err) + return VIR_ERR_OK; + return err->code; +} + + +/** + * virGetLastErrorDomain: + * + * Get the most recent error domain + * + * The error object is kept in thread local storage, so separate + * threads can safely access this concurrently. + * + * Returns the most recent error code in this thread, + * or VIR_FROM_NONE if none is set + */ +int +virGetLastErrorDomain(void) +{ + virErrorPtr err = virLastErrorObject(); + if (!err) + return VIR_FROM_NONE; + return err->domain; +} + + +/** * virGetLastErrorMessage: * * Get the most recent error message -- 2.7.4

On Fri, May 04, 2018 at 04:46:47AM +0100, ramyelkest wrote:
Many places in the code call virGetLastError() just to check the raised error code, or domain. However virGetLastError() can return NULL, so the code has to check for that as well.
s/as well/first.
So Instead we create functions virGetLastErrorCode and virGetLastErrorDomain (in addition to the existing virGetLastErrorMessage) that always return a valid error code/domain/message, to simplify callers.
No paragraph, how about "This patch therefore introduces virGetLasErrorCode function which always returns a valid error code, thus dropping the need to perform any checks on the error object".
Also created virHasLastErrorCode for completion
My first commit, for: https://wiki.libvirt.org/page/BiteSizedTasks#Add_and_use_virGetLastErrorCode...
You mentioned this in the cover letter already, no need to have it in the commit messages too ;).
Signed-off-by: Ramy Elkest <ramyelkest@gmail.com> --- include/libvirt/virterror.h | 3 +++ src/libvirt_public.syms | 7 +++++ src/util/virerror.c | 63 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 73 insertions(+)
diff --git a/include/libvirt/virterror.h b/include/libvirt/virterror.h index 3e7c7a0..8336258 100644 --- a/include/libvirt/virterror.h +++ b/include/libvirt/virterror.h @@ -344,6 +344,9 @@ void virResetLastError (void); void virResetError (virErrorPtr err); void virFreeError (virErrorPtr err);
+int virHasLastError (void); +int virGetLastErrorCode (void); +int virGetLastErrorDomain (void); const char * virGetLastErrorMessage (void);
virErrorPtr virConnGetLastError (virConnectPtr conn); diff --git a/src/libvirt_public.syms b/src/libvirt_public.syms index 95df3a0..3a641a3 100644 --- a/src/libvirt_public.syms +++ b/src/libvirt_public.syms @@ -785,4 +785,11 @@ LIBVIRT_4.1.0 { virStoragePoolLookupByTargetPath; } LIBVIRT_3.9.0;
+LIBVIRT_4.4.0 { + global: + virHasLastError; + virGetLastErrorCode; + virGetLastErrorDomain; +} LIBVIRT_4.1.0; + # .... define new API here using predicted next version number .... diff --git a/src/util/virerror.c b/src/util/virerror.c index c000b00..818af2e 100644 --- a/src/util/virerror.c +++ b/src/util/virerror.c @@ -272,6 +272,69 @@ virGetLastError(void)
/** + * virHasLastError: + * + * Check for a reported last error + * + * The error object is kept in thread local storage, so separate + * threads can safely access this concurrently. + * + * Returns 1 if there is an error and the error code is not VIR_ERR_OK, + otherwise returns 0 + */ +int +virHasLastError(void) +{ + virErrorPtr err = virLastErrorObject(); + if (!err || err->code == VIR_ERR_OK) + return 0; + return 1; +}
As you noted in the cover letter, ^this one is essentially identical to virGetLastErrorCode, minus the "1 vs err->code" and since VIR_ERR_OK == 0, you can use virGetLastErrorCode the same way as you used virHasLastError as a replacement in many occurrences of virGetLastError(), so I don't see the need for this function.
+ + +/** + * virGetLastErrorCode: + * + * Get the most recent error code + * + * The error object is kept in thread local storage, so separate + * threads can safely access this concurrently. + * + * Returns the most recent error code in this thread, + * or VIR_ERR_OK if none is set + */ +int +virGetLastErrorCode(void) +{ + virErrorPtr err = virLastErrorObject(); + if (!err) + return VIR_ERR_OK; + return err->code; +} + + +/** + * virGetLastErrorDomain: + * + * Get the most recent error domain + * + * The error object is kept in thread local storage, so separate + * threads can safely access this concurrently. + * + * Returns the most recent error code in this thread, + * or VIR_FROM_NONE if none is set + */ +int +virGetLastErrorDomain(void) +{ + virErrorPtr err = virLastErrorObject(); + if (!err) + return VIR_FROM_NONE; + return err->domain; +}
I can see a need for ^this function, even though we don't have an immediate use case for it internally, it's still a public API which someone else might consume, otherwise they'd have to query the object itself. Erik

Many places in the code call virGetLastError() just to check the raised error code, or domain. However virGetLastError() can return NULL, so the code has to check for that as well. So Instead we create functions virGetLastErrorCode and virGetLastErrorDomain (in addition to the existing virGetLastErrorMessage) that always return a valid error code/domain/message, to simplify callers. Also created virHasLastErrorCode for completion for: https://wiki.libvirt.org/page/BiteSizedTasks#Add_and_use_virGetLastErrorCode... Notes: * There are a few instances of virGetLastErrorCode() left where we use multiple fields from the error, which makes sense to keep it. * I didn't manage to use virGetLastErrorDomain() (due to the above) so I'm inclined to remove it. Signed-off-by: Ramy Elkest <ramyelkest@gmail.com> --- src/locking/lock_driver_lockd.c | 3 +-- src/lxc/lxc_controller.c | 4 +--- src/qemu/qemu_agent.c | 3 +-- src/qemu/qemu_conf.c | 3 +-- src/qemu/qemu_domain.c | 2 +- src/qemu/qemu_driver.c | 12 ++++++------ src/qemu/qemu_hotplug.c | 2 +- src/qemu/qemu_migration.c | 4 ++-- src/qemu/qemu_monitor.c | 5 ++--- src/qemu/qemu_monitor_json.c | 2 +- src/qemu/qemu_process.c | 2 +- src/remote/remote_driver.c | 3 +-- src/rpc/virnetclient.c | 2 +- src/util/virfilecache.c | 3 +-- src/util/virxml.c | 4 ++-- tests/commandtest.c | 2 +- tests/testutils.c | 6 ++---- tests/virhostcputest.c | 2 +- tests/virstoragetest.c | 8 ++++---- tools/virsh-domain-monitor.c | 7 +++---- tools/virsh-domain.c | 4 +--- tools/virsh-util.c | 3 +-- tools/vsh.c | 2 +- 23 files changed, 37 insertions(+), 51 deletions(-) diff --git a/src/locking/lock_driver_lockd.c b/src/locking/lock_driver_lockd.c index c3fc18a..957a963 100644 --- a/src/locking/lock_driver_lockd.c +++ b/src/locking/lock_driver_lockd.c @@ -302,8 +302,7 @@ static int virLockManagerLockDaemonSetupLockspace(const char *path) 0, NULL, NULL, NULL, (xdrproc_t)xdr_virLockSpaceProtocolCreateLockSpaceArgs, (char*)&args, (xdrproc_t)xdr_void, NULL) < 0) { - virErrorPtr err = virGetLastError(); - if (err && err->code == VIR_ERR_OPERATION_INVALID) { + if (virGetLastErrorCode() == VIR_ERR_OPERATION_INVALID) { /* The lockspace already exists */ virResetLastError(); rv = 0; diff --git a/src/lxc/lxc_controller.c b/src/lxc/lxc_controller.c index d5636b8..81709d5 100644 --- a/src/lxc/lxc_controller.c +++ b/src/lxc/lxc_controller.c @@ -1297,7 +1297,6 @@ static void virLXCControllerConsoleIO(int watch, int fd, int events, void *opaqu */ static int virLXCControllerMain(virLXCControllerPtr ctrl) { - virErrorPtr err; int rc = -1; size_t i; @@ -1349,8 +1348,7 @@ static int virLXCControllerMain(virLXCControllerPtr ctrl) virNetDaemonRun(ctrl->daemon); - err = virGetLastError(); - if (!err || err->code == VIR_ERR_OK) + if (!virHasLastError()) rc = wantReboot ? 1 : 0; cleanup: diff --git a/src/qemu/qemu_agent.c b/src/qemu/qemu_agent.c index 4df1bde..0d7a484 100644 --- a/src/qemu/qemu_agent.c +++ b/src/qemu/qemu_agent.c @@ -686,8 +686,7 @@ qemuAgentIO(int watch, int fd, int events, void *opaque) /* Already have an error, so clear any new error */ virResetLastError(); } else { - virErrorPtr err = virGetLastError(); - if (!err) + if (!virHasLastError()) virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Error while processing monitor IO")); virCopyLastError(&mon->lastError); diff --git a/src/qemu/qemu_conf.c b/src/qemu/qemu_conf.c index bfbb572..a09532d 100644 --- a/src/qemu/qemu_conf.c +++ b/src/qemu/qemu_conf.c @@ -297,8 +297,7 @@ virQEMUDriverConfigPtr virQEMUDriverConfigNew(bool privileged) if (privileged && virFileFindHugeTLBFS(&cfg->hugetlbfs, &cfg->nhugetlbfs) < 0) { /* This however is not implemented on all platforms. */ - virErrorPtr err = virGetLastError(); - if (err && err->code != VIR_ERR_NO_SUPPORT) + if (virGetLastErrorCode() != VIR_ERR_NO_SUPPORT) goto error; } diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c index 727ea33..7df1520 100644 --- a/src/qemu/qemu_domain.c +++ b/src/qemu/qemu_domain.c @@ -6063,7 +6063,7 @@ int qemuDomainObjExitMonitor(virQEMUDriverPtr driver, { qemuDomainObjExitMonitorInternal(driver, obj); if (!virDomainObjIsActive(obj)) { - if (!virGetLastError()) + if (!virHasLastError()) virReportError(VIR_ERR_OPERATION_FAILED, "%s", _("domain is no longer running")); return -1; diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 83fc191..7a313b5 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -1929,7 +1929,7 @@ static int qemuDomainResume(virDomainPtr dom) if (qemuProcessStartCPUs(driver, vm, VIR_DOMAIN_RUNNING_UNPAUSED, QEMU_ASYNC_JOB_NONE) < 0) { - if (virGetLastError() == NULL) + if (!virHasLastError()) virReportError(VIR_ERR_OPERATION_FAILED, "%s", _("resume operation failed")); goto endjob; @@ -3209,7 +3209,7 @@ qemuFileWrapperFDClose(virDomainObjPtr vm, ret = virFileWrapperFdClose(fd); virObjectLock(vm); if (!virDomainObjIsActive(vm)) { - if (!virGetLastError()) + if (!virHasLastError()) virReportError(VIR_ERR_OPERATION_FAILED, "%s", _("domain is no longer running")); ret = -1; @@ -3991,7 +3991,7 @@ qemuDomainCoreDumpWithFormat(virDomainPtr dom, event = virDomainEventLifecycleNewFromObj(vm, VIR_DOMAIN_EVENT_SUSPENDED, VIR_DOMAIN_EVENT_SUSPENDED_API_ERROR); - if (virGetLastError() == NULL) + if (!virHasLastError()) virReportError(VIR_ERR_OPERATION_FAILED, "%s", _("resuming after dump failed")); } @@ -6638,7 +6638,7 @@ qemuDomainSaveImageStartVM(virConnectPtr conn, if (qemuProcessStartCPUs(driver, vm, VIR_DOMAIN_RUNNING_RESTORED, asyncJob) < 0) { - if (virGetLastError() == NULL) + if (!virHasLastError()) virReportError(VIR_ERR_OPERATION_FAILED, "%s", _("failed to resume domain")); goto cleanup; @@ -14084,7 +14084,7 @@ qemuDomainSnapshotCreateActiveInternal(virQEMUDriverPtr driver, event = virDomainEventLifecycleNewFromObj(vm, VIR_DOMAIN_EVENT_SUSPENDED, VIR_DOMAIN_EVENT_SUSPENDED_API_ERROR); - if (virGetLastError() == NULL) { + if (!virHasLastError()) { virReportError(VIR_ERR_OPERATION_FAILED, "%s", _("resuming after snapshot failed")); } @@ -15048,7 +15048,7 @@ qemuDomainSnapshotCreateActiveExternal(virQEMUDriverPtr driver, VIR_DOMAIN_EVENT_SUSPENDED, VIR_DOMAIN_EVENT_SUSPENDED_API_ERROR); qemuDomainEventQueue(driver, event); - if (virGetLastError() == NULL) { + if (!virHasLastError()) { virReportError(VIR_ERR_OPERATION_FAILED, "%s", _("resuming after snapshot failed")); } diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c index 9ca8e66..831582f 100644 --- a/src/qemu/qemu_hotplug.c +++ b/src/qemu/qemu_hotplug.c @@ -212,7 +212,7 @@ qemuHotplugWaitForTrayEject(virQEMUDriverPtr driver, if (rc > 0) { /* the caller called qemuMonitorEjectMedia which usually reports an * error. Report the failure in an off-chance that it didn't. */ - if (!virGetLastError()) { + if (!virHasLastError()) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("timed out waiting for disk tray status update")); } diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c index 7602a30..a4b3434 100644 --- a/src/qemu/qemu_migration.c +++ b/src/qemu/qemu_migration.c @@ -4944,7 +4944,7 @@ qemuMigrationDstFinish(virQEMUDriverPtr driver, inPostCopy ? VIR_DOMAIN_RUNNING_POSTCOPY : VIR_DOMAIN_RUNNING_MIGRATED, QEMU_ASYNC_JOB_MIGRATION_IN) < 0) { - if (virGetLastError() == NULL) + if (!virHasLastError()) virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("resume operation failed")); /* Need to save the current error, in case shutting @@ -5082,7 +5082,7 @@ qemuMigrationDstFinish(virQEMUDriverPtr driver, /* Set a special error if Finish is expected to return NULL as a result of * successful call with retcode != 0 */ - if (retcode != 0 && !dom && !virGetLastError()) + if (retcode != 0 && !dom && !virHasLastError()) virReportError(VIR_ERR_MIGRATE_FINISH_OK, NULL); return dom; } diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c index 3918791..31b303d 100644 --- a/src/qemu/qemu_monitor.c +++ b/src/qemu/qemu_monitor.c @@ -752,8 +752,7 @@ qemuMonitorIO(int watch, int fd, int events, void *opaque) /* Already have an error, so clear any new error */ virResetLastError(); } else { - virErrorPtr err = virGetLastError(); - if (!err) + if (!virHasLastError()) virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Error while processing monitor IO")); virCopyLastError(&mon->lastError); @@ -1032,7 +1031,7 @@ qemuMonitorClose(qemuMonitorPtr mon) /* Propagate existing monitor error in case the current thread has no * error set. */ - if (mon->lastError.code != VIR_ERR_OK && !virGetLastError()) + if (mon->lastError.code != VIR_ERR_OK && !virHasLastError()) virSetError(&mon->lastError); virObjectUnlock(mon); diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c index 8176175..6cc2db1 100644 --- a/src/qemu/qemu_monitor_json.c +++ b/src/qemu/qemu_monitor_json.c @@ -4338,7 +4338,7 @@ qemuMonitorJSONDiskNameLookup(qemuMonitorPtr mon, } /* Guarantee an error when returning NULL, but don't override a * more specific error if one was already generated. */ - if (!ret && !virGetLastError()) + if (!ret && !virHasLastError()) virReportError(VIR_ERR_INTERNAL_ERROR, _("unable to find backing name for device %s"), device); diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c index 37876b8..58524d0 100644 --- a/src/qemu/qemu_process.c +++ b/src/qemu/qemu_process.c @@ -558,7 +558,7 @@ qemuProcessFakeReboot(void *opaque) if (qemuProcessStartCPUs(driver, vm, reason, QEMU_ASYNC_JOB_NONE) < 0) { - if (virGetLastError() == NULL) + if (!virHasLastError()) virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("resume operation failed")); goto endjob; diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c index 95437b4..e670e16 100644 --- a/src/remote/remote_driver.c +++ b/src/remote/remote_driver.c @@ -3672,8 +3672,7 @@ remoteAuthenticate(virConnectPtr conn, struct private_data *priv, (xdrproc_t) xdr_void, (char *) NULL, (xdrproc_t) xdr_remote_auth_list_ret, (char *) &ret); if (err < 0) { - virErrorPtr verr = virGetLastError(); - if (verr && verr->code == VIR_ERR_NO_SUPPORT) { + if (virGetLastErrorCode() == VIR_ERR_NO_SUPPORT) { /* Missing RPC - old server - ignore */ virResetLastError(); return 0; diff --git a/src/rpc/virnetclient.c b/src/rpc/virnetclient.c index 6bbc984..365485a 100644 --- a/src/rpc/virnetclient.c +++ b/src/rpc/virnetclient.c @@ -1958,7 +1958,7 @@ static int virNetClientIO(virNetClientPtr client, virNetClientIOUpdateCallback(client, true); if (rv == 0 && - virGetLastError()) + virHasLastError()) rv = -1; cleanup: diff --git a/src/util/virfilecache.c b/src/util/virfilecache.c index dab7216..96ae96d 100644 --- a/src/util/virfilecache.c +++ b/src/util/virfilecache.c @@ -157,9 +157,8 @@ virFileCacheLoad(virFileCachePtr cache, } if (!(loadData = cache->handlers.loadFile(file, name, cache->priv))) { - virErrorPtr err = virGetLastError(); VIR_WARN("Failed to load cached data from '%s' for '%s': %s", - file, name, err ? NULLSTR(err->message) : "unknown error"); + file, name, virGetLastErrorMessage()); virResetLastError(); ret = 0; goto cleanup; diff --git a/src/util/virxml.c b/src/util/virxml.c index 6e87605..3d3d08e 100644 --- a/src/util/virxml.c +++ b/src/util/virxml.c @@ -708,7 +708,7 @@ catchXMLError(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) /* conditions for error printing */ if (!ctxt || - (virGetLastError() != NULL) || + (virHasLastError()) || ctxt->input == NULL || ctxt->lastError.level != XML_ERR_FATAL || ctxt->lastError.message == NULL) @@ -845,7 +845,7 @@ virXMLParseHelper(int domcode, xmlFreeDoc(xml); xml = NULL; - if (virGetLastError() == NULL) { + if (!virHasLastError()) { virGenericReportError(domcode, VIR_ERR_XML_ERROR, "%s", _("failed to parse xml document")); } diff --git a/tests/commandtest.c b/tests/commandtest.c index ad81c2a..06eecba 100644 --- a/tests/commandtest.c +++ b/tests/commandtest.c @@ -127,7 +127,7 @@ static int test0(const void *unused ATTRIBUTE_UNUSED) if (virCommandRun(cmd, NULL) == 0) goto cleanup; - if (virGetLastError() == NULL) + if (!virHasLastError()) goto cleanup; virResetLastError(); diff --git a/tests/testutils.c b/tests/testutils.c index 4b13d11..9bef446 100644 --- a/tests/testutils.c +++ b/tests/testutils.c @@ -178,8 +178,7 @@ virTestRun(const char *title, virResetLastError(); ret = body(data); - virErrorPtr err = virGetLastError(); - if (err) { + if (virHasLastError()) { if (virTestGetVerbose() || virTestGetDebug()) virDispatchError(NULL); } @@ -258,8 +257,7 @@ virTestRun(const char *title, fprintf(stderr, " alloc %zu failed but no err status\n", i + 1); # endif } else { - virErrorPtr lerr = virGetLastError(); - if (!lerr) { + if (!virHasLastError()) { # if 0 fprintf(stderr, " alloc %zu failed but no error report\n", i + 1); # endif diff --git a/tests/virhostcputest.c b/tests/virhostcputest.c index cb318df..34cf015 100644 --- a/tests/virhostcputest.c +++ b/tests/virhostcputest.c @@ -49,7 +49,7 @@ linuxTestCompareFiles(const char *cpuinfofile, &nodeinfo.nodes, &nodeinfo.sockets, &nodeinfo.cores, &nodeinfo.threads) < 0) { if (virTestGetDebug()) { - if (virGetLastError()) + if (virHasLastError()) VIR_TEST_DEBUG("\n%s\n", virGetLastErrorMessage()); } VIR_FORCE_FCLOSE(cpuinfo); diff --git a/tests/virstoragetest.c b/tests/virstoragetest.c index 0e11602..adc3ae7 100644 --- a/tests/virstoragetest.c +++ b/tests/virstoragetest.c @@ -333,7 +333,7 @@ testStorageChain(const void *args) goto cleanup; } if (data->flags & EXP_WARN) { - if (!virGetLastError()) { + if (!virHasLastError()) { fprintf(stderr, "call should have warned\n"); goto cleanup; } @@ -343,7 +343,7 @@ testStorageChain(const void *args) goto cleanup; } } else { - if (virGetLastError()) { + if (virHasLastError()) { fprintf(stderr, "call should not have warned\n"); goto cleanup; } @@ -449,13 +449,13 @@ testStorageLookup(const void *args) idx, NULL); if (!data->expResult) { - if (!virGetLastError()) { + if (!virHasLastError()) { fprintf(stderr, "call should have failed\n"); ret = -1; } virResetLastError(); } else { - if (virGetLastError()) { + if (virHasLastError()) { fprintf(stderr, "call should not have warned\n"); ret = -1; } diff --git a/tools/virsh-domain-monitor.c b/tools/virsh-domain-monitor.c index 8e07177..32099cb 100644 --- a/tools/virsh-domain-monitor.c +++ b/tools/virsh-domain-monitor.c @@ -63,7 +63,6 @@ virshGetDomainDescription(vshControl *ctl, virDomainPtr dom, bool title, unsigned int flags) { char *desc = NULL; - virErrorPtr err = NULL; xmlDocPtr doc = NULL; xmlXPathContextPtr ctxt = NULL; int type; @@ -76,15 +75,15 @@ virshGetDomainDescription(vshControl *ctl, virDomainPtr dom, bool title, if ((desc = virDomainGetMetadata(dom, type, NULL, flags))) { return desc; } else { - err = virGetLastError(); + int errCode = virGetLastErrorCode(); - if (err && err->code == VIR_ERR_NO_DOMAIN_METADATA) { + if (errCode == VIR_ERR_NO_DOMAIN_METADATA) { desc = vshStrdup(ctl, ""); vshResetLibvirtError(); return desc; } - if (err && err->code != VIR_ERR_NO_SUPPORT) + if (errCode != VIR_ERR_NO_SUPPORT) return desc; } diff --git a/tools/virsh-domain.c b/tools/virsh-domain.c index 2b775fc..54f00dc 100644 --- a/tools/virsh-domain.c +++ b/tools/virsh-domain.c @@ -94,9 +94,7 @@ virshDomainDefine(virConnectPtr conn, const char *xml, unsigned int flags) * try again. */ if (!dom) { - virErrorPtr err = virGetLastError(); - if (err && - (err->code == VIR_ERR_NO_SUPPORT) && + if ((virGetLastErrorCode() == VIR_ERR_NO_SUPPORT) && (flags == VIR_DOMAIN_DEFINE_VALIDATE)) dom = virDomainDefineXML(conn, xml); } diff --git a/tools/virsh-util.c b/tools/virsh-util.c index 44be3ad..aa88397 100644 --- a/tools/virsh-util.c +++ b/tools/virsh-util.c @@ -123,8 +123,7 @@ virshDomainState(vshControl *ctl, if (!priv->useGetInfo) { int state; if (virDomainGetState(dom, &state, reason, 0) < 0) { - virErrorPtr err = virGetLastError(); - if (err && err->code == VIR_ERR_NO_SUPPORT) + if (virGetLastErrorCode() == VIR_ERR_NO_SUPPORT) priv->useGetInfo = true; else return -1; diff --git a/tools/vsh.c b/tools/vsh.c index 73ec007..8799cd2 100644 --- a/tools/vsh.c +++ b/tools/vsh.c @@ -266,7 +266,7 @@ vshSaveLibvirtHelperError(void) if (last_error) return; - if (!virGetLastError()) + if (!virHasLastError()) return; vshSaveLibvirtError(); -- 2.7.4

On Fri, May 04, 2018 at 04:46:48AM +0100, ramyelkest wrote:
Many places in the code call virGetLastError() just to check the raised error code, or domain. However virGetLastError() can return NULL, so the code has to check for that as well.
So Instead we create functions virGetLastErrorCode and virGetLastErrorDomain (in addition to the existing virGetLastErrorMessage) that always return a valid error code/domain/message, to simplify callers.
Also created virHasLastErrorCode for completion
for: https://wiki.libvirt.org/page/BiteSizedTasks#Add_and_use_virGetLastErrorCode...
Notes: * There are a few instances of virGetLastErrorCode() left where we use multiple fields from the error, which makes sense to keep it. * I didn't manage to use virGetLastErrorDomain() (due to the above) so I'm inclined to remove it.
Same comments to the commit message as for patch 1. ...
Signed-off-by: Ramy Elkest <ramyelkest@gmail.com> --- src/locking/lock_driver_lockd.c | 3 +-- src/lxc/lxc_controller.c | 4 +--- src/qemu/qemu_agent.c | 3 +-- src/qemu/qemu_conf.c | 3 +-- src/qemu/qemu_domain.c | 2 +- src/qemu/qemu_driver.c | 12 ++++++------ src/qemu/qemu_hotplug.c | 2 +- src/qemu/qemu_migration.c | 4 ++-- src/qemu/qemu_monitor.c | 5 ++--- src/qemu/qemu_monitor_json.c | 2 +- src/qemu/qemu_process.c | 2 +- src/remote/remote_driver.c | 3 +-- src/rpc/virnetclient.c | 2 +- src/util/virfilecache.c | 3 +-- src/util/virxml.c | 4 ++-- tests/commandtest.c | 2 +- tests/testutils.c | 6 ++---- tests/virhostcputest.c | 2 +- tests/virstoragetest.c | 8 ++++---- tools/virsh-domain-monitor.c | 7 +++---- tools/virsh-domain.c | 4 +--- tools/virsh-util.c | 3 +-- tools/vsh.c | 2 +- 23 files changed, 37 insertions(+), 51 deletions(-)
I found 2 more occurrences in src/util/virnetlibsshsession.c (l.502) and src/util/virmodule.c (l.126) respectively, which can be optimized too. ...
if (!(loadData = cache->handlers.loadFile(file, name, cache->priv))) { - virErrorPtr err = virGetLastError(); VIR_WARN("Failed to load cached data from '%s' for '%s': %s", - file, name, err ? NULLSTR(err->message) : "unknown error"); + file, name, virGetLastErrorMessage());
Good catch, although, this should be a separate patch IMO, let's say patch 1 and then the rest of the series. On a side note, I looked whether there aren't other places which could use the virGetLastErrorMessage, sadly no, since the interface isn't really flexible (among other problems with the whole error subsystem) so that when there's no error we report "unknown error" which is good as nothing, so providing a custom string in case there's no error or we can't identify it would probably have been a smarter choice, oh well... Other than that I'm fine with the changes (v2 shouldn't be a problem). Erik
participants (2)
-
Erik Skultety
-
ramyelkest