[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: Questionable aspects of QEMU Error's design
From: |
Markus Armbruster |
Subject: |
Re: Questionable aspects of QEMU Error's design |
Date: |
Fri, 03 Apr 2020 09:09:27 +0200 |
User-agent: |
Gnus/5.13 (Gnus v5.13) Emacs/26.3 (gnu/linux) |
BALATON Zoltan <address@hidden> writes:
> On Thu, 2 Apr 2020, Markus Armbruster wrote:
>> Vladimir Sementsov-Ogievskiy <address@hidden> writes:
>>> 02.04.2020 12:36, BALATON Zoltan wrote:
[...]
>>>> Not much better. Could it be something like:
[...]
>>>> ERRP_RET(object_property_set_link(cpuobj,
>>>> OBJECT(&s->cpu_container[i]),
>>>> "memory", errp));
>>>> ERRP_RET(object_property_set_link(cpuobj, OBJECT(s), "idau", errp));
>>>> ERRP_RET(object_property_set_bool(cpuobj, true, "realized", errp));
>>>>
>>>
>>> and turn all
>>>
>>> ret = func(...);
>>> if (ret < 0) {
>>> return ret;
>>> }
>>>
>>> into
>>>
>>> FAIL_RET(func(...))
>>>
>>> ?
>>>
>>> Not a problem to make such macro.. But I think it's a bad idea to turn all
>>> the code
>>> into sequence of macro invocations. It's hard to debug and follow.
>>
>> Yes. Hiding control flow in macros is almost always too much magic.
>> There are exceptions, but this doesn't look like one.
>
> I did't like this idea of mine too much either so I agree but I see no
> other easy way to simplify this. If you propose changing function
> return values maybe these should return errp instead of passing it as
> a func parameter? Could that result in simpler code and less macro
> magic needed?
I don't think so. Let's compare a few error handling patterns from
error.h.
* Call a function and receive an error from it:
* Error *err = NULL;
* foo(arg, &err);
* if (err) {
* handle the error...
* }
Making foo() return the error object instead of void looks like an
obvious win:
if (foo(arg)) {
handle the error...
}
Except it does not work, because surely a use of @err is hiding in
"handle the error" (or else we'd leak it). So you actually need
err = foo(arg)
if (err) {
handle the error...
}
All this saves you is initializing @err.
You can save a bit more
if ((err = foo(arg))) {
handle the error...
}
We generally frown upon assignemnts within if controlling expressions.
Next:
* Receive an error and pass it on to the caller:
[...]
* But when all you do with the error is pass it on, please use
* foo(arg, errp);
* for readability.
The obvious conversion
*errp = foo(arg);
is wrong for !errp, errp == &error_fatal, and errp == &error_abort.
You'd need
err = foo(arg);
error_propagate(errp, err);
or, if you're so inclined
error_propagate(errp, foo(arg));
Less legible, and it creates and destroys error objects where the
current method doesn't.
Returning the error object is even less attractive for functions that
now return values.
- Re: Questionable aspects of QEMU Error's design, (continued)
Re: Questionable aspects of QEMU Error's design, Markus Armbruster, 2020/04/02
- Re: Questionable aspects of QEMU Error's design, Vladimir Sementsov-Ogievskiy, 2020/04/02
- Re: Questionable aspects of QEMU Error's design, Peter Maydell, 2020/04/02
- Re: Questionable aspects of QEMU Error's design, Daniel P . Berrangé, 2020/04/02
- Re: Questionable aspects of QEMU Error's design, Markus Armbruster, 2020/04/02
- Re: Questionable aspects of QEMU Error's design, Vladimir Sementsov-Ogievskiy, 2020/04/02
- Re: Questionable aspects of QEMU Error's design, Markus Armbruster, 2020/04/02
- Re: Questionable aspects of QEMU Error's design, Vladimir Sementsov-Ogievskiy, 2020/04/02
- Re: Questionable aspects of QEMU Error's design, Markus Armbruster, 2020/04/03
Re: Questionable aspects of QEMU Error's design, Paolo Bonzini, 2020/04/02