<div dir="ltr">Sorry for not looking at it.  I'm mostly ok with the API so it's fine that you pushed it.  I did have a question or two though.<br><div class="gmail_extra"><br><br><div class="gmail_quote">On Mon, Jul 7, 2014 at 7:28 AM, Pekka Paalanen <span dir="ltr"><<a href="mailto:ppaalanen@gmail.com" target="_blank">ppaalanen@gmail.com</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">From: Marek Chalupa <<a href="mailto:mchqwerty@gmail.com">mchqwerty@gmail.com</a>><br>
<br>
When an error occurs, wl_display_get_error() does not<br>
provide any way of getting know if it was a local error or if it was<br>
an error event, respectively what object caused the error and what<br>
the error was.<br>
<br>
This patch introduces a new function wl_display_get_protocol_error()<br>
which will return error code, interface and id of the object that<br>
generated the error.<br>
wl_display_get_error() will work the same way as before.<br>
<br>
wl_display_get_protocol_error() DOES NOT indicate that a non-protocol<br>
error happened. It returns valid information only in that case that<br>
(protocol) error occurred, so it should be used after calling<br>
wl_display_get_error() with positive result.<br>
<br>
[Pekka Paalanen] Applied another hunk of Bryce's comments to docs,<br>
        added libtool version bump.<br>
<br>
Reviewed-by: Pekka Paalanen <<a href="mailto:ppaalanen@gmail.com">ppaalanen@gmail.com</a>><br>
Reviewed-by: Bryce Harrington <<a href="mailto:b.harrington@samsung.com">b.harrington@samsung.com</a>><br>
---<br>
 Makefile.am          |   2 +-<br>
 src/wayland-client.c | 137 ++++++++++++++++++++++++++++++++++++++++++++-------<br>
 src/wayland-client.h |   3 ++<br>
 3 files changed, 123 insertions(+), 19 deletions(-)<br>
<br>
diff --git a/Makefile.am b/Makefile.am<br>
index c15d8b8..fee19ab 100644<br>
--- a/Makefile.am<br>
+++ b/Makefile.am<br>
@@ -51,7 +51,7 @@ nodist_libwayland_server_la_SOURCES =         \<br>
<br>
 libwayland_client_la_CFLAGS = $(FFI_CFLAGS) $(GCC_CFLAGS) -pthread<br>
 libwayland_client_la_LIBADD = $(FFI_LIBS) <a href="http://libwayland-util.la" target="_blank">libwayland-util.la</a> -lrt -lm<br>
-libwayland_client_la_LDFLAGS = -version-info 2:0:2<br>
+libwayland_client_la_LDFLAGS = -version-info 3:0:3<br>
 libwayland_client_la_SOURCES =                 \<br>
        src/wayland-client.c<br>
<br>
diff --git a/src/wayland-client.c b/src/wayland-client.c<br>
index e8aab7e..19b5694 100644<br>
--- a/src/wayland-client.c<br>
+++ b/src/wayland-client.c<br>
@@ -78,7 +78,24 @@ struct wl_event_queue {<br>
 struct wl_display {<br>
        struct wl_proxy proxy;<br>
        struct wl_connection *connection;<br>
+<br>
+       /* errno of the last wl_display error */<br>
        int last_error;<br>
+<br>
+       /* When display gets an error event from some object, it stores<br>
+        * information about it here, so that client can get this<br>
+        * information afterwards */<br>
+       struct {<br>
+               /* Code of the error. It can be compared to<br>
+                * the interface's errors enumeration. */<br>
+               uint32_t code;<br>
+               /* interface (protocol) in which the error occurred */<br>
+               const struct wl_interface *interface;<br>
+               /* id of the proxy that caused the error. There's no warranty<br>
+                * that the proxy is still valid. It's up to client how it will<br>
+                * use it */<br>
+               uint32_t id;<br>
+       } protocol_error;<br>
        int fd;<br>
        pthread_t display_thread;<br>
        struct wl_map objects;<br>
@@ -96,6 +113,14 @@ struct wl_display {<br>
<br>
 static int debug_client = 0;<br>
<br>
+/**<br>
+ * This function is called for local errors (no memory, server hung up)<br>
+ *<br>
+ * \param display<br>
+ * \param error    error value (EINVAL, EFAULT, ...)<br>
+ *<br>
+ * \note this function is called with display mutex locked<br>
+ */<br>
 static void<br>
 display_fatal_error(struct wl_display *display, int error)<br>
 {<br>
@@ -105,7 +130,7 @@ display_fatal_error(struct wl_display *display, int error)<br>
                return;<br>
<br>
        if (!error)<br>
-               error = 1;<br>
+               error = EFAULT;<br>
<br>
        display->last_error = error;<br>
<br>
@@ -113,11 +138,56 @@ display_fatal_error(struct wl_display *display, int error)<br>
                pthread_cond_broadcast(&iter->cond);<br>
 }<br>
<br>
+/**<br>
+ * This function is called for error events<br>
+ * and indicates that in some object an error occured.<br>
+ * Difference between this function and display_fatal_error()<br>
+ * is that this one handles errors that will come by wire,<br>
+ * whereas display_fatal_error() is called for local errors.<br>
+ *<br>
+ * \param display<br>
+ * \param code    error code<br>
+ * \param id      id of the object that generated the error<br>
+ * \param intf    protocol interface<br>
+ */<br>
 static void<br>
-wl_display_fatal_error(struct wl_display *display, int error)<br>
+display_protocol_error(struct wl_display *display, uint32_t code,<br>
+                      uint32_t id, const struct wl_interface *intf)<br>
 {<br>
+       struct wl_event_queue *iter;<br>
+       int err;<br>
+<br>
+       if (display->last_error)<br>
+               return;<br>
+<br>
+       /* set correct errno */<br>
+       if (wl_interface_equal(intf, &wl_display_interface)) {<br>
+               switch (code) {<br>
+               case WL_DISPLAY_ERROR_INVALID_OBJECT:<br>
+               case WL_DISPLAY_ERROR_INVALID_METHOD:<br>
+                       err = EINVAL;<br>
+                       break;<br>
+               case WL_DISPLAY_ERROR_NO_MEMORY:<br>
+                       err = ENOMEM;<br>
+                       break;<br>
+               default:<br>
+                       err = EFAULT;<br>
+               }<br>
+       } else {<br>
+               err = EPROTO;<br>
+       }<br>
+<br>
        pthread_mutex_lock(&display->mutex);<br>
-       display_fatal_error(display, error);<br>
+<br>
+       display->last_error = err;<br>
+<br>
+       display->protocol_error.code = code;<br>
+       display-><a href="http://protocol_error.id" target="_blank">protocol_error.id</a> = id;<br>
+       display->protocol_error.interface = intf;<br>
+<br>
+       wl_list_for_each(iter, &display->event_queue_list, link)<br>
+               pthread_cond_broadcast(&iter->cond);<br></blockquote><div><br></div><div>Why are you doing this?  Is someone waiting on you to display an error or waiting for the error code?  I don't really see what there is to wake up here.<br>
</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
+<br>
        pthread_mutex_unlock(&display->mutex);<br>
 }<br>
<br>
@@ -579,25 +649,12 @@ display_handle_error(void *data,<br>
                     uint32_t code, const char *message)<br>
 {<br>
        struct wl_proxy *proxy = object;<br>
-       int err;<br>
<br>
        wl_log("%s@%u: error %d: %s\n",<br>
               proxy->object.interface->name, proxy-><a href="http://object.id" target="_blank">object.id</a>, code, message);<br>
<br>
-       switch (code) {<br>
-       case WL_DISPLAY_ERROR_INVALID_OBJECT:<br>
-       case WL_DISPLAY_ERROR_INVALID_METHOD:<br>
-               err = EINVAL;<br>
-               break;<br>
-       case WL_DISPLAY_ERROR_NO_MEMORY:<br>
-               err = ENOMEM;<br>
-               break;<br>
-       default:<br>
-               err = EFAULT;<br>
-               break;<br>
-       }<br>
-<br>
-       wl_display_fatal_error(display, err);<br>
+       display_protocol_error(display, code, proxy-><a href="http://object.id" target="_blank">object.id</a>,<br>
+                              proxy->object.interface);<br>
 }<br>
<br>
 static void<br>
@@ -1486,6 +1543,50 @@ wl_display_get_error(struct wl_display *display)<br>
        return ret;<br>
 }<br>
<br>
+/**<br>
+ * Retrieves the information about a protocol error:<br>
+ *<br>
+ * \param display    The Wayland display<br>
+ * \param interface  if not NULL, stores the interface where the error occurred<br>
+ * \param id         if not NULL, stores the object id that generated<br>
+ *                   the error. There's no guarantee the object is<br>
+ *                   still valid; the client must know if it deleted the object.<br></blockquote><div><br></div><div>Does the client even know what to do with the ID?  I mean, sure, they could print it in an error message, but how useful is it?  I suppose they could check to see if wl_proxy_get_id(my_proxy) == id to see if it happend at that point in the stream.  Is this what you intend?<br>
</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
+ * \return           The error code as defined in the interface specification.<br>
+ *<br>
+ * \code<br>
+ * int err = wl_display_get_error(display);<br>
+ *<br>
+ * if (err == EPROTO) {<br>
+ *        code = wl_display_get_protocol_error(display, &interface, &id);<br>
+ *        handle_error(code, interface, id);<br>
+ * }<br>
+ *<br>
+ * ...<br>
+ *<br>
+ *  \endcode<br>
+ */<br>
+WL_EXPORT uint32_t<br>
+wl_display_get_protocol_error(struct wl_display *display,<br>
+                             const struct wl_interface **interface,<br>
+                             uint32_t *id)<br>
+{<br>
+       uint32_t ret;<br>
+<br>
+       pthread_mutex_lock(&display->mutex);<br>
+<br>
+       ret = display->protocol_error.code;<br>
+<br>
+       if (interface)<br>
+               *interface = display->protocol_error.interface;<br>
+       if (id)<br>
+               *id = display-><a href="http://protocol_error.id" target="_blank">protocol_error.id</a>;<br>
+<br>
+       pthread_mutex_unlock(&display->mutex);<br>
+<br>
+       return ret;<br>
+}<br>
+<br>
+<br>
 /** Send all buffered requests on the display to the server<br>
  *<br>
  * \param display The display context object<br>
diff --git a/src/wayland-client.h b/src/wayland-client.h<br>
index 2a32785..dc4df53 100644<br>
--- a/src/wayland-client.h<br>
+++ b/src/wayland-client.h<br>
@@ -161,6 +161,9 @@ int wl_display_dispatch_queue_pending(struct wl_display *display,<br>
                                      struct wl_event_queue *queue);<br>
 int wl_display_dispatch_pending(struct wl_display *display);<br>
 int wl_display_get_error(struct wl_display *display);<br>
+uint32_t wl_display_get_protocol_error(struct wl_display *display,<br>
+                                      const struct wl_interface **interface,<br>
+                                      uint32_t *id);<br>
<br>
 int wl_display_flush(struct wl_display *display);<br>
 int wl_display_roundtrip(struct wl_display *display);<br>
<span class="HOEnZb"><font color="#888888">--<br>
1.8.5.5<br>
<br>
_______________________________________________<br>
wayland-devel mailing list<br>
<a href="mailto:wayland-devel@lists.freedesktop.org">wayland-devel@lists.freedesktop.org</a><br>
<a href="http://lists.freedesktop.org/mailman/listinfo/wayland-devel" target="_blank">http://lists.freedesktop.org/mailman/listinfo/wayland-devel</a><br>
</font></span></blockquote></div><br></div></div>