<html><head></head><body><div class="gmail_quote">On 20 November 2018 8:02:50 pm NZDT, Christopher James Halse Rogers <christopher.halse.rogers@canonical.com> wrote:<blockquote class="gmail_quote" style="margin: 0pt 0pt 0pt 0.8ex; border-left: 1px solid rgb(204, 204, 204); padding-left: 1ex;">
<pre class="k9mail">Many languages such as C++ or Rust have an unwinding error-reporting<br>mechanism. Code in these languages can (and must!) wrap request handling<br>callbacks in unwind guards to avoid undefined behaviour.<br><br>As a consequence such code will detect internal server errors, but have<br>no way to communicate such failures to the client.<br><br>This adds a WL_DISPLAY_ERROR_IMPLEMENTATION error to wl_display so that<br>such code can notify (and disconnect) clients which hit internal bugs.<br>While servers can currently abuse other wl_display errors for the same<br>effect, adding an explicit error code allows clients to tell the<br>difference between errors which are their fault and errors which are the<br>server's fault. This is particularly interesting for automated bug<br>reporting.<br><br>v2: Rename error from "internal" to "implementation", in sympathy with<br>    X11's BadImplementation error.<br>    Add more justification in the commit message.<br><br>Signed-off-by: Christopher James Halse Rogers <christopher.halse.rogers@canonical.com><br>Acked-by: Pekka Paalanen <pekka.paalanen@collabora.co.uk><hr> protocol/wayland.xml      |  2 ++<br> src/wayland-client.c      |  3 +++<br> src/wayland-server-core.h |  4 ++++<br> src/wayland-server.c      | 24 +++++++++++++++++++++++<br> tests/display-test.c      | 40 +++++++++++++++++++++++++++++++++++++++<br> 5 files changed, 73 insertions(+)<br><br>diff --git a/protocol/wayland.xml b/protocol/wayland.xml<br>index 141038b..754b789 100644<br>--- a/protocol/wayland.xml<br>+++ b/protocol/wayland.xml<br>@@ -94,6 +94,8 @@<br>        summary="method doesn't exist on the specified interface"/><br>       <entry name="no_memory" value="2"<br>             summary="server is out of memory"/><br>+      <entry name="implementation" value="3"<br>+       summary="implementation error in compositor"/><br>     </enum><br> <br>     <event name="delete_id"><br>diff --git a/src/wayland-client.c b/src/wayland-client.c<br>index 0ccfc66..b0805f1 100644<br>--- a/src/wayland-client.c<br>+++ b/src/wayland-client.c<br>@@ -185,6 +185,9 @@ display_protocol_error(struct wl_display *display, uint32_t code,<br>                case WL_DISPLAY_ERROR_NO_MEMORY:<br>                      err = ENOMEM;<br>                         break;<br>+               case WL_DISPLAY_ERROR_IMPLEMENTATION:<br>+                        err = EPROTO;<br>+                        break;<br>                default:<br>                      err = EFAULT;<br>                 }<br>diff --git a/src/wayland-server-core.h b/src/wayland-server-core.h<br>index 2e725d9..3e0272b 100644<br>--- a/src/wayland-server-core.h<br>+++ b/src/wayland-server-core.h<br>@@ -324,6 +324,10 @@ wl_client_get_object(struct wl_client *client, uint32_t id);<br> void<br> wl_client_post_no_memory(struct wl_client *client);<br> <br>+void<br>+wl_client_post_implementation_error(struct wl_client *client,<br>+                                    const char* msg, ...) WL_PRINTF(2,3);<br>+<br> void<br> wl_client_add_resource_created_listener(struct wl_client *client,<br>                                         struct wl_listener *listener);<br>diff --git a/src/wayland-server.c b/src/wayland-server.c<br>index c0ad229..19f6a76 100644<br>--- a/src/wayland-server.c<br>+++ b/src/wayland-server.c<br>@@ -650,6 +650,30 @@ wl_client_post_no_memory(struct wl_client *client)<br>                                WL_DISPLAY_ERROR_NO_MEMORY, "no memory");<br> }<br> <br>+/** Report an internal server error<br>+ *<br>+ * \param client The client object<br>+ * \param msg A printf-style format string<br>+ * \param ... Format string arguments<br>+ *<br>+ * Report an unspecified internal implementation error and disconnect<br>+ * the client.<br>+ *<br>+ * \memberof wl_client<br>+ */<br>+WL_EXPORT void<br>+wl_client_post_implementation_error(struct wl_client *client,<br>+                                char const *msg, ...)<br>+{<br>+        va_list ap;<br>+<br>+       va_start(ap, msg);<br>+   wl_resource_post_error_vargs(client->display_resource,<br>+                                 WL_DISPLAY_ERROR_IMPLEMENTATION,<br>+                                     msg, ap);<br>+       va_end(ap);<br>+}<br>+<br> WL_EXPORT void<br> wl_resource_post_no_memory(struct wl_resource *resource)<br> {<br>diff --git a/tests/display-test.c b/tests/display-test.c<br>index 9b49a0e..6d98cc7 100644<br>--- a/tests/display-test.c<br>+++ b/tests/display-test.c<br>@@ -419,6 +419,46 @@ TEST(post_nomem_tst)<br>        display_destroy(d);<br> }<br> <br>+static void<br>+post_implementation_error_main(void)<br>+{<br>+  struct client *c = client_connect();<br>+ struct wl_seat *seat = client_get_seat(c);<br>+   uint32_t object_id, protocol_error;<br>+  const struct wl_interface *interface;<br>+<br>+     assert(stop_display(c, 1) == -1);<br>+    int err = wl_display_get_error(c->wl_display);<br>+    fprintf(stderr, "Err is %i\n", err);<br>+       assert(err == EPROTO);<br>+       protocol_error = wl_display_get_protocol_error(c->wl_display,<br>+                                                    &interface,<br>+                                                      &object_id);<br>+      assert(protocol_error == WL_DISPLAY_ERROR_IMPLEMENTATION);<br>+   assert(interface == &wl_display_interface);<br>+<br>+   wl_proxy_destroy((struct wl_proxy *) seat);<br>+  client_disconnect_nocheck(c);<br>+}<br>+<br>+TEST(post_internal_error_tst)<br>+{<br>+     struct display *d = display_create();<br>+        struct client_info *cl;<br>+<br>+   wl_global_create(d->wl_display, &wl_seat_interface,<br>+                    1, d, bind_seat);<br>+<br>+        cl = client_create_noarg(d, post_implementation_error_main);<br>+ display_run(d);<br>+<br>+   wl_client_post_implementation_error(cl->wl_client, "Error %i", 20);<br>+<br>+  display_resume(d);<br>+<br>+        display_destroy(d);<br>+}<br>+<br> static void<br> register_reading(struct wl_display *display)<br> {</pre></blockquote></div><br clear="all">Ping!<br><br>Is there anything I can do to make these patches more appealing?</body></html>