util: set OOM in virCopyLastError if error is not set

virCopyLastError is intended to be used after last error is set.
However due to virLastErrorObject failures (very unlikely though
as thread local error is allocated on first use) we can have zero
fields in a copy as a result. In particular code field can be set
to VIR_ERR_OK.

In some places (qemu monitor, qemu agent and qemu migaration code
for example) we use copy result as a flag and this leads to bugs.

Let's set OOM-like error in copy in case of virLastErrorObject failures.

Signed-off-by: Nikolay Shirokovskiy <nshirokovskiy@virtuozzo.com>
This commit is contained in:
Nikolay Shirokovskiy 2018-07-02 14:16:52 +03:00
parent 36d426a611
commit 1bff5bbe25
2 changed files with 12 additions and 5 deletions

@ -1 +1 @@
Subproject commit cdbf3d385a32ff904c96f20c26f3470bd8345248 Subproject commit d6397dde2e127e246e3eeb5254a21f42cac783c8

View File

@ -366,19 +366,26 @@ virSetError(virErrorPtr newerr)
* *
* One will need to free the result with virResetError() * One will need to free the result with virResetError()
* *
* Returns 0 if no error was found and the error code otherwise and -1 in case * Returns error code or -1 in case of parameter error.
* of parameter error.
*/ */
int int
virCopyLastError(virErrorPtr to) virCopyLastError(virErrorPtr to)
{ {
virErrorPtr err = virLastErrorObject(); virErrorPtr err = virLastErrorObject();
if (!to)
return -1;
/* We can't guarantee caller has initialized it to zero */ /* We can't guarantee caller has initialized it to zero */
memset(to, 0, sizeof(*to)); memset(to, 0, sizeof(*to));
if (err) if (err) {
virCopyError(err, to); virCopyError(err, to);
else } else {
virResetError(to); virResetError(to);
to->code = VIR_ERR_NO_MEMORY;
to->domain = VIR_FROM_NONE;
to->level = VIR_ERR_ERROR;
}
return to->code; return to->code;
} }