On 2025/08/08 17:08, Markus Armbruster wrote:
We added @error_warn some two years ago in commit 3ffef1a55ca (error:
add global &error_warn destination).  It has multiple issues:

* error.h's big comment was not updated for it.

* Function contracts were not updated for it.

* ERRP_GUARD() is unaware of @error_warn, and fails to mask it from
   error_prepend() and such.  These crash on @error_warn, as pointed
   out by Akihiko Odaki.

All fixable.  However, after more than two years, we had just of 15
uses, of which the last few patches removed eight as unclean or
otherwise undesirable.  I didn't look closely enough at the remaining
seven to decide whether they are desirable or not.

I don't think this feature earns its keep.  Drop it.

I want to note that the following patch series temporarily use &error_warn during its conversion to add errp parameters:
https://lore.kernel.org/qemu-devel/20250808-propagate_tpm_error-v10-0-3e81a1d41...@redhat.com/
("[PATCH v10 00/27] migration: propagate vTPM errors using Error objects")

I think this series needs to be rebased on top of the migration change.

I'm not sure if seven uses are insufficient to keep it.

I also have a general impression that perhaps a special error destination for error_report_err() is more useful. Today, there are many functions use Error, but there are also functions that still follow old error handling patterns. When legacy functions call functions with Error, a common pattern is to use error_report_err() and return -1.

"[PATCH 01/12] monitor: Clean up HMP gdbserver error reporting" and "[PATCH 09/12] ui/pixman: Consistent error handling in qemu_pixman_shareable_free()" are examples that will benefit from error_report_err() as an error destination. The migration patch series I mentioned earlier can also use one.

Perhaps it is nicer if there is an infrastructure shared by the special destinations. In particular, we can have common solutions for the three problems you pointed out:

> * error.h's big comment was not updated for it.
>
> * Function contracts were not updated for it.

For these two problems, they can refer to "special error destinations" instead of listing them, and delegate explanations of them to corresponding ones.

>
> * ERRP_GUARD() is unaware of @error_warn, and fails to mask it from
>    error_prepend() and such.  These crash on @error_warn, as pointed
>    out by Akihiko Odaki.

For this problem, Error can tell that it is a special destination by leaving msg NULL, for example. ERRP_GUARD() then rewrites errp it is not &error_abort and msg is NULL.

Special destinations can also have a function pointer void (*)(Error*), which will be called by error_handle(). This way, we can ensure that having a special destination will not require changes to the common code.

By the way, I also asked for a comment with the migration patch series. Please reply the following if you have anything to say:
https://lore.kernel.org/qemu-devel/9c552525-72fa-4d1e-89a2-b5c0e4469...@rsg.ci.i.u-tokyo.ac.jp/

There is also an additional context:
https://lore.kernel.org/qemu-devel/ajmsrbd9-xomr...@armenon-kvm.bengluru.csb/

Regards,
Akihiko Odaki


Thanks-to: Akihiko  Odaki <od...@rsg.ci.i.u-tokyo.ac.jp>
Signed-off-by: Markus Armbruster <arm...@redhat.com>
---
  include/qapi/error.h           |  6 ------
  hw/display/virtio-gpu.c        |  8 ++++++--
  hw/net/virtio-net.c            |  8 +++++++-
  tests/unit/test-error-report.c | 17 -----------------
  ui/gtk.c                       |  6 +++++-
  util/error.c                   |  5 +----
  6 files changed, 19 insertions(+), 31 deletions(-)

diff --git a/include/qapi/error.h b/include/qapi/error.h
index 41e3816380..b16c6303f8 100644
--- a/include/qapi/error.h
+++ b/include/qapi/error.h
@@ -533,12 +533,6 @@ static inline void 
error_propagator_cleanup(ErrorPropagator *prop)
G_DEFINE_AUTO_CLEANUP_CLEAR_FUNC(ErrorPropagator, error_propagator_cleanup); -/*
- * Special error destination to warn on error.
- * See error_setg() and error_propagate() for details.
- */
-extern Error *error_warn;
-
  /*
   * Special error destination to abort on error.
   * See error_setg() and error_propagate() for details.
diff --git a/hw/display/virtio-gpu.c b/hw/display/virtio-gpu.c
index 0a1a625b0e..de35902213 100644
--- a/hw/display/virtio-gpu.c
+++ b/hw/display/virtio-gpu.c
@@ -242,6 +242,7 @@ static uint32_t calc_image_hostmem(pixman_format_code_t 
pformat,
  static void virtio_gpu_resource_create_2d(VirtIOGPU *g,
                                            struct virtio_gpu_ctrl_command *cmd)
  {
+    Error *err = NULL;
      pixman_format_code_t pformat;
      struct virtio_gpu_simple_resource *res;
      struct virtio_gpu_resource_create_2d c2d;
@@ -293,7 +294,8 @@ static void virtio_gpu_resource_create_2d(VirtIOGPU *g,
                  c2d.width,
                  c2d.height,
                  c2d.height ? res->hostmem / c2d.height : 0,
-                &error_warn)) {
+                &err)) {
+            warn_report_err(err);
              goto end;
          }
      }
@@ -1282,6 +1284,7 @@ static int virtio_gpu_load(QEMUFile *f, void *opaque, 
size_t size,
                             const VMStateField *field)
  {
      VirtIOGPU *g = opaque;
+    Error *err = NULL;
      struct virtio_gpu_simple_resource *res;
      uint32_t resource_id, pformat;
      int i;
@@ -1317,7 +1320,8 @@ static int virtio_gpu_load(QEMUFile *f, void *opaque, 
size_t size,
                                               res->width,
                                               res->height,
                                               res->height ? res->hostmem / 
res->height : 0,
-                                             &error_warn)) {
+                                             &err)) {
+            warn_report_err(err);
              g_free(res);
              return -EINVAL;
          }
diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c
index 6b5b5dace3..7848e26278 100644
--- a/hw/net/virtio-net.c
+++ b/hw/net/virtio-net.c
@@ -1289,6 +1289,8 @@ exit:
static bool virtio_net_load_ebpf(VirtIONet *n, Error **errp)
  {
+    Error *err = NULL;
+
      if (!virtio_net_attach_ebpf_to_backend(n->nic, -1)) {
          return true;
      }
@@ -1306,7 +1308,11 @@ static bool virtio_net_load_ebpf(VirtIONet *n, Error 
**errp)
          return virtio_net_load_ebpf_fds(n, errp);
      }
- ebpf_rss_load(&n->ebpf_rss, &error_warn);
+    ebpf_rss_load(&n->ebpf_rss, &err);
+    /* Beware, ebpf_rss_load() can return false with @err unset */
+    if (err) {
+        warn_report_err(err);
+    }
      return true;
  }
diff --git a/tests/unit/test-error-report.c b/tests/unit/test-error-report.c
index 54319c86c9..0cbde3c4cf 100644
--- a/tests/unit/test-error-report.c
+++ b/tests/unit/test-error-report.c
@@ -104,22 +104,6 @@ test_error_report_timestamp(void)
  ");
  }
-static void
-test_error_warn(void)
-{
-    if (g_test_subprocess()) {
-        error_setg(&error_warn, "Testing &error_warn");
-        return;
-    }
-
-    g_test_trap_subprocess(NULL, 0, 0);
-    g_test_trap_assert_passed();
-    g_test_trap_assert_stderr("\
-test-error-report: warning: Testing &error_warn*\
-");
-}
-
-
  int
  main(int argc, char *argv[])
  {
@@ -133,7 +117,6 @@ main(int argc, char *argv[])
      g_test_add_func("/error-report/glog", test_error_report_glog);
      g_test_add_func("/error-report/once", test_error_report_once);
      g_test_add_func("/error-report/timestamp", test_error_report_timestamp);
-    g_test_add_func("/error-report/warn", test_error_warn);
return g_test_run();
  }
diff --git a/ui/gtk.c b/ui/gtk.c
index e91d093a49..9a08cadc88 100644
--- a/ui/gtk.c
+++ b/ui/gtk.c
@@ -1181,6 +1181,7 @@ static gboolean gd_touch_event(GtkWidget *widget, 
GdkEventTouch *touch,
                                 void *opaque)
  {
      VirtualConsole *vc = opaque;
+    Error *err = NULL;
      uint64_t num_slot = GPOINTER_TO_UINT(touch->sequence);
      int type = -1;
@@ -1203,7 +1204,10 @@ static gboolean gd_touch_event(GtkWidget *widget, GdkEventTouch *touch,
      console_handle_touch_event(vc->gfx.dcl.con, touch_slots,
                                 num_slot, surface_width(vc->gfx.ds),
                                 surface_height(vc->gfx.ds), touch->x,
-                               touch->y, type, &error_warn);
+                               touch->y, type, &err);
+    if (err) {
+        warn_report_err(err);
+    }
      return TRUE;
  }
diff --git a/util/error.c b/util/error.c
index daea2142f3..0ae08225c0 100644
--- a/util/error.c
+++ b/util/error.c
@@ -19,7 +19,6 @@
Error *error_abort;
  Error *error_fatal;
-Error *error_warn;
static void error_handle(Error **errp, Error *err)
  {
@@ -41,9 +40,7 @@ static void error_handle(Error **errp, Error *err)
          error_report_err(err);
          exit(1);
      }
-    if (errp == &error_warn) {
-        warn_report_err(err);
-    } else if (errp && !*errp) {
+    if (errp && !*errp) {
          *errp = err;
      } else {
          error_free(err);


Reply via email to