From: Markus Armbruster <armbru@redhat.com>
To: Paolo Bonzini <pbonzini@redhat.com>
Cc: Zhao Liu <zhao1.liu@intel.com>,
qemu-devel@nongnu.org, qemu-rust@nongnu.org
Subject: Re: [PATCH 06/14] rust: qemu-api: add bindings to Error
Date: Wed, 04 Jun 2025 07:01:05 +0200 [thread overview]
Message-ID: <871ps02j8u.fsf@pond.sub.org> (raw)
In-Reply-To: <2b7be73c-d91f-4820-a8ad-6964a8331150@redhat.com> (Paolo Bonzini's message of "Tue, 3 Jun 2025 17:05:59 +0200")
Paolo Bonzini <pbonzini@redhat.com> writes:
> On 6/3/25 12:32, Markus Armbruster wrote:
>>> Then Rust's propagate has the same behavior as C (Of course, here Rust
>>> is actually using C's error_propagate, so the two are equivalent.)
>>
>> *If* we want propagate semantics. I'm not sure we do.
>
> Yes, we do. This function is used at the Rust-to-C boundary and should
> behave exactly like C functions would: it will get an Error ** from the
> callers and needs to propagate the just-created Error* into it.
Well, how *do* C functions behave?
* = Rules =
*
* - Functions that use Error to report errors have an Error **errp
* parameter. It should be the last parameter, except for functions
* taking variable arguments.
*
* - You may pass NULL to not receive the error, &error_abort to abort
* on error, &error_fatal to exit(1) on error, or a pointer to a
* variable containing NULL to receive the error.
For later... This is a precondition. passing a pointer to a variable
containing anything but NULL violates the precondition.
*
* - Separation of concerns: the function is responsible for detecting
* errors and failing cleanly; handling the error is its caller's
* job. Since the value of @errp is about handling the error, the
* function should not examine it.
*
* - The function may pass @errp to functions it calls to pass on
* their errors to its caller. If it dereferences @errp to check
* for errors, it must use ERRP_GUARD().
*
* - On success, the function should not touch *errp. On failure, it
* should set a new error, e.g. with error_setg(errp, ...), or
* propagate an existing one, e.g. with error_propagate(errp, ...).
This is what your FOO_or_propagate() functions are for.
The rule glosses over a subtle detail: the difference between
error_setg() and error_propagate() isn't just create a new error vs. use
an existing one, namely error_setg() makes the precondition violation
mentioned above a programming error, whereas error_propagate() does not,
it instead *ignores* the error it's supposed to propagate.
I consider this difference a design mistake. Note that GError avoids
this mistake: g_error_propagate() requieres the destination to NULL or
point to NULL. We deviated from GError, because we thought we were
smarter. We weren't.
Mostly harmless in practice, as behavior is identical for callers that
satisfy the preconditions.
*
* - Whenever practical, also return a value that indicates success /
* failure. This can make the error checking more concise, and can
* avoid useless error object creation and destruction. Note that
* we still have many functions returning void. We recommend
* • bool-valued functions return true on success / false on failure,
* • pointer-valued functions return non-null / null pointer, and
* • integer-valued functions return non-negative / negative.
So here's the bottom line. We want a Rust function to use C Error
according to its written rules. Due to a design mistake, C functions
can behave in two different ways when their caller violates a certain
precondition, depending on how the function transmits the error to the
caller. For Rust functions, we can
* Always behave the more common way, i.e. like a C function using
error_setg() to transmit.
* Always behave the less common way, i.e. like a C function using
error_propagate() to transmit.
* Sometimes one way, sometimes the other way.
This is actually in order of decreasing personal preference. But what
do *you* think?
> In fact, I had found this issue already last Friday, but then didn't
> inform you because of the (long) weekend. Apologies for that.
No harm, no foul :)
next prev parent reply other threads:[~2025-06-04 5:01 UTC|newest]
Thread overview: 34+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-05-30 8:02 [PATCH v2 00/14] rust: bindings for Error Paolo Bonzini
2025-05-30 8:02 ` [PATCH 01/14] subprojects: add the anyhow crate Paolo Bonzini
2025-05-30 8:02 ` [PATCH 02/14] subprojects: add the foreign crate Paolo Bonzini
2025-05-30 8:02 ` [PATCH 03/14] util/error: expose Error definition to Rust code Paolo Bonzini
2025-06-03 3:06 ` Zhao Liu
2025-05-30 8:02 ` [PATCH 04/14] util/error: allow non-NUL-terminated err->src Paolo Bonzini
2025-06-02 10:47 ` Markus Armbruster
2025-05-30 8:02 ` [PATCH 05/14] util/error: make func optional Paolo Bonzini
2025-06-02 10:52 ` Markus Armbruster
2025-05-30 8:02 ` [PATCH 06/14] rust: qemu-api: add bindings to Error Paolo Bonzini
2025-06-02 13:18 ` Markus Armbruster
2025-06-03 9:29 ` Zhao Liu
2025-06-03 10:32 ` Markus Armbruster
2025-06-03 15:05 ` Paolo Bonzini
2025-06-04 5:01 ` Markus Armbruster [this message]
2025-06-04 19:19 ` Paolo Bonzini
2025-06-05 6:14 ` Markus Armbruster
2025-06-03 15:37 ` Paolo Bonzini
2025-05-30 8:02 ` [PATCH 07/14] rust: qemu-api: add tests for Error bindings Paolo Bonzini
2025-05-30 8:03 ` [PATCH 08/14] rust: qdev: support returning errors from realize Paolo Bonzini
2025-05-30 8:03 ` [PATCH 09/14] rust/hpet: change type of num_timers to usize Paolo Bonzini
2025-05-30 8:03 ` [PATCH 10/14] hpet: adjust VMState for consistency with Rust version Paolo Bonzini
2025-06-03 3:11 ` Zhao Liu
2025-05-30 8:03 ` [PATCH 11/14] hpet: return errors from realize if properties are incorrect Paolo Bonzini
2025-05-30 8:03 ` [PATCH 12/14] rust/hpet: " Paolo Bonzini
2025-05-30 8:03 ` [PATCH 13/14] rust/hpet: Drop BqlCell wrapper for num_timers Paolo Bonzini
2025-05-30 8:03 ` [PATCH 14/14] docs: update Rust module status Paolo Bonzini
2025-06-03 3:09 ` Zhao Liu
2025-06-02 7:49 ` [PATCH v2 00/14] rust: bindings for Error Markus Armbruster
2025-06-02 9:45 ` Paolo Bonzini
2025-06-03 9:35 ` Zhao Liu
-- strict thread matches above, loose matches on Subject: below --
2025-06-05 10:15 [PATCH v3 " Paolo Bonzini
2025-06-05 10:15 ` [PATCH 06/14] rust: qemu-api: add bindings to Error Paolo Bonzini
2025-06-05 12:06 ` Markus Armbruster
2025-06-05 13:45 ` Zhao Liu
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=871ps02j8u.fsf@pond.sub.org \
--to=armbru@redhat.com \
--cc=pbonzini@redhat.com \
--cc=qemu-devel@nongnu.org \
--cc=qemu-rust@nongnu.org \
--cc=zhao1.liu@intel.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.