Eric Blake <ebl...@redhat.com> writes:

> On 06/17/2015 01:24 AM, Michael S. Tsirkin wrote:
>> makes it possible to copy error_abort pointers,
>> not just pass them on directly.
>> 
>
>> @@ -168,7 +175,7 @@ void error_free(Error *err)
>>  
>>  void error_propagate(Error **dst_errp, Error *local_err)
>>  {
>> -    if (local_err && dst_errp == &error_abort) {
>> +    if (local_err && error_is_abort(dst_errp)) {
>>          error_report_err(local_err);
>>          abort();
>>      } else if (dst_errp && !*dst_errp) {
>
> As I pointed out on 3/3, this breaks code that does:
>
> if (local_err) {
>     error_propagate(errp, local_err);
>     ...
> }
>
> now that local_err is non-NULL when errp is error_abort.  But what if
> you alter the semantics, and have error_propagate return a bool (true if
> an error was propagated, false if no error or caller didn't care):
>
> bool error_propagate(Error **dst_errp, Error *local_err)
> {
>     if (error_is_abort(&local_err)) {
>         assert(error_is_abort(dst_errp);
>         return false;
>     }
>     if (local_err && error_is_abort(dst_errp)) {
>         error_report_err(local_err);
>         abort();
>     }
>     if (dst_errp && !*dst_errp) {
>         *dst_errp = local_err;
>         return true;
>     }
>     if (local_err) {
>         error_free(local_err);
>     }
>     return false;
> }
>
> then callers can be modified to this idiom (also has the benefit of
> being one line shorter):
>
> if (error_propagate(errp, local_err)) {
>     ...
> }

Caution!  The condition you need to test here is "an error has been
stored into local_err", *not* "an error was propagated".  Different when
errp is NULL and local_err has an error.

Reply via email to