Re: [PATCH v3] client: extend error handling

2014-05-07 Thread Pekka Paalanen
On Wed,  7 May 2014 16:21:24 +0200
Marek Chalupa  wrote:

> When an error occurs, wl_display_get_error() does not
> provide any way of getting know if it was a local error or if it was
> an error event, respectively what object caused the error and what
> the error was.
> 
> This patch introduces a new function wl_display_get_protocol_error()
> which will return error code, interface and id of the object that
> generated the error.
> wl_display_get_error() will work the same way as before.
> 
> wl_display_get_protocol_error() DOES NOT indicate that a non-protocol
> error happened. It returns valid information only in that case that
> (protocol) error occurred, so it should be used after calling
> wl_display_get_error() with positive result.
> 
> Thanks to Pekka Paalanen  for pointing out
> issues in the first versions of this patch.
> ---
>  src/wayland-client.c | 138 
> ---
>  src/wayland-client.h |   3 ++
>  2 files changed, 123 insertions(+), 18 deletions(-)
> 
> diff --git a/src/wayland-client.c b/src/wayland-client.c
> index bd40313..c9f8f4f 100644
> --- a/src/wayland-client.c
> +++ b/src/wayland-client.c
> @@ -78,7 +78,24 @@ struct wl_event_queue {
>  struct wl_display {
>   struct wl_proxy proxy;
>   struct wl_connection *connection;
> +
> + /* errno of the last wl_display error */
>   int last_error;
> +
> + /* When display gets an error event from some object, it stores
> +  * information about it here, so that client can get this
> +  * information afterwards */
> + struct {
> + /* Code of the error. It can be compared to
> +  * the interface's errors enumeration. */
> + uint32_t code;
> + /* interface (protocol) in which the error occurred */
> + const struct wl_interface *interface;
> + /* id of the proxy that caused the error. There's no warranty
> +  * that the proxy is still valid. It's up to client how it will
> +  * use it */
> + uint32_t id;
> + } protocol_error;
>   int fd;
>   pthread_t display_thread;
>   struct wl_map objects;
> @@ -96,6 +113,14 @@ struct wl_display {
>  
>  static int debug_client = 0;
>  
> +/**
> + * This function is called for local errors (no memory, server hung up)
> + *
> + * \param display
> + * \param errorerror value (EINVAL, EFAULT, ...)
> + *
> + * \note this function is called with display mutex locked
> + */
>  static void
>  display_fatal_error(struct wl_display *display, int error)
>  {
> @@ -105,7 +130,7 @@ display_fatal_error(struct wl_display *display, int error)
>   return;
>  
>   if (!error)
> - error = 1;
> + error = EFAULT;
>  
>   display->last_error = error;
>  
> @@ -113,11 +138,56 @@ display_fatal_error(struct wl_display *display, int 
> error)
>   pthread_cond_broadcast(&iter->cond);
>  }
>  
> +/**
> + * This function is called for error events
> + * and idicates that in some object occured an error.
> + * Difference between this function and display_fatal_error()
> + * is that this one handles errors that will come in wire, whereas
> + * display_fatal_error() is called for local errors.
> + *
> + * \param display
> + * \param codeerror code
> + * \param id  id of the object that generated the error
> + * \param intfprotocol interface
> + */
>  static void
> -wl_display_fatal_error(struct wl_display *display, int error)
> +display_protocol_error(struct wl_display *display, uint32_t code,
> +uint32_t id, const struct wl_interface *intf)
>  {
> + struct wl_event_queue *iter;
> + int err;
> +
> + if (display->last_error)
> + return;
> +
> + /* set correct errno */
> + if (wl_interface_equal(intf, &wl_display_interface)) {
> + switch (code) {
> + case WL_DISPLAY_ERROR_INVALID_OBJECT:
> + case WL_DISPLAY_ERROR_INVALID_METHOD:
> + err = EINVAL;
> + break;
> + case WL_DISPLAY_ERROR_NO_MEMORY:
> + err = ENOMEM;
> + break;
> + default:
> + err = EFAULT;
> + }
> + } else {
> + err = EPROTO;
> + }
> +
>   pthread_mutex_lock(&display->mutex);
> - display_fatal_error(display, error);
> +
> + display->last_error = err;
> +
> + display->protocol_error.code = code;
> + display->protocol_error.id = id;
> + display->protocol_error.interface = intf;
> +
> + wl_list_for_each(iter, &display->event_queue_list, link)
> + pthread_cond_broadcast(&iter->cond);
> +
>   pthread_mutex_unlock(&display->mutex);
>  }
>  
> @@ -579,25 +649,12 @@ display_handle_error(void *data,
>uint32_t code, const char *message)
>  {
>   struct wl_proxy *proxy = object;
> - int err;
>  
>   wl_log("%s

Re: [PATCH v3] client: extend error handling

2014-05-07 Thread Marek Chalupa
On 5 May 2014 15:02, Pekka Paalanen  wrote:

> On Wed, 30 Apr 2014 10:11:01 +0200
> Marek Chalupa  wrote:
>
> > When an error occurs, wl_display_get_error() does not
> > provide any way of getting know if it was a local error or if it was
> > an error event, respectively what object caused the error and what
> > the error was.
> >
> > This patch introduces a new function wl_display_get_protocol_error()
> > which will return error code, interface and id of the object that
> > generated the error.
> > wl_display_get_error() will work the same way as before.
> >
> > wl_display_get_protocol_error() DOES NOT indicate that a non-protocol
> > error happened. It returns valid information only in that case that
> > (protocol) error occurred, so it should be used after calling
> > wl_display_get_error() with positive result.
> >
> > Thanks to Pekka Paalanen  for pointing out
> > issues in the first versions of this patch.
> > ---
> >  src/wayland-client.c | 138
> ---
> >  src/wayland-client.h |   3 ++
> >  2 files changed, 123 insertions(+), 18 deletions(-)
> >
> > diff --git a/src/wayland-client.c b/src/wayland-client.c
> > index bd40313..8dd8804 100644
> > --- a/src/wayland-client.c
> > +++ b/src/wayland-client.c
> > @@ -78,7 +78,24 @@ struct wl_event_queue {
> >  struct wl_display {
> >   struct wl_proxy proxy;
> >   struct wl_connection *connection;
> > +
> > + /* errno of the last wl_display error */
> >   int last_error;
> > +
> > + /* When display gets an error event from some object, it stores
> > +  * information about it here, so that client can get this
> > +  * information afterwards */
> > + struct {
> > + /* Code of the error. It can be compared to
> > +  * the interface's errors enumeration. */
> > + int code;
>
> I just checked in wl_display::error specification, and the type of the
> error code is uint32_t.
>
> > + /* interface (protocol) in which the error occurred */
> > + const struct wl_interface *interface;
> > + /* id of the proxy that caused the error. There's no
> warranty
> > +  * that the proxy is still valid. It's up to client how it
> will
> > +  * use it */
> > + uint32_t id;
> > + } protocol_error;
> >   int fd;
> >   pthread_t display_thread;
> >   struct wl_map objects;
> > @@ -96,6 +113,14 @@ struct wl_display {
> >
> >  static int debug_client = 0;
> >
> > +/**
> > + * This function is called for local errors (no memory, server hung up)
> > + *
> > + * \param display
> > + * \param errorerror value (EINVAL, EFAULT, ...)
> > + *
> > + * \note this function is called with display mutex locked
> > + */
> >  static void
> >  display_fatal_error(struct wl_display *display, int error)
> >  {
> > @@ -105,7 +130,7 @@ display_fatal_error(struct wl_display *display, int
> error)
> >   return;
> >
> >   if (!error)
> > - error = 1;
> > + error = EFAULT;
> >
> >   display->last_error = error;
> >
> > @@ -113,11 +138,56 @@ display_fatal_error(struct wl_display *display,
> int error)
> >   pthread_cond_broadcast(&iter->cond);
> >  }
> >
> > +/**
> > + * This function is called for error events
> > + * and idicates that in some object occured an error.
> > + * Difference between this function and display_fatal_error()
> > + * is that this one handles errors that will come in wire, whereas
> > + * display_fatal_error() is called for local errors.
> > + *
> > + * \param display
> > + * \param codeerror code
> > + * \param id  id of the object that generated the error
> > + * \param intfprotocol interface
> > + */
> >  static void
> > -wl_display_fatal_error(struct wl_display *display, int error)
> > +display_protocol_error(struct wl_display *display, int code,
> > +unsigned int id, const struct wl_interface *intf)
> >  {
> > + struct wl_event_queue *iter;
> > + int err;
> > +
> > + if (display->last_error)
> > + return;
> > +
> > + /* set correct errno */
> > + if (wl_interface_equal(intf, &wl_display_interface)) {
> > + switch (code) {
> > + case WL_DISPLAY_ERROR_INVALID_OBJECT:
> > + case WL_DISPLAY_ERROR_INVALID_METHOD:
> > + err = EINVAL;
> > + break;
> > + case WL_DISPLAY_ERROR_NO_MEMORY:
> > + err = ENOMEM;
> > + break;
> > + default:
> > + err = EFAULT;
> > + }
> > + } else {
> > + err = EPROTO;
> > + }
> > +
> >   pthread_mutex_lock(&display->mutex);
> > - display_fatal_error(display, error);
> > +
> > + display->last_error = err;
> > +
> > + display->protocol_error.code = code;
> > + display->protocol_error.id = id;
> > + display->protocol_error.interface 

[PATCH v3] client: extend error handling

2014-05-07 Thread Marek Chalupa
When an error occurs, wl_display_get_error() does not
provide any way of getting know if it was a local error or if it was
an error event, respectively what object caused the error and what
the error was.

This patch introduces a new function wl_display_get_protocol_error()
which will return error code, interface and id of the object that
generated the error.
wl_display_get_error() will work the same way as before.

wl_display_get_protocol_error() DOES NOT indicate that a non-protocol
error happened. It returns valid information only in that case that
(protocol) error occurred, so it should be used after calling
wl_display_get_error() with positive result.

Thanks to Pekka Paalanen  for pointing out
issues in the first versions of this patch.
---
 src/wayland-client.c | 138 ---
 src/wayland-client.h |   3 ++
 2 files changed, 123 insertions(+), 18 deletions(-)

diff --git a/src/wayland-client.c b/src/wayland-client.c
index bd40313..c9f8f4f 100644
--- a/src/wayland-client.c
+++ b/src/wayland-client.c
@@ -78,7 +78,24 @@ struct wl_event_queue {
 struct wl_display {
struct wl_proxy proxy;
struct wl_connection *connection;
+
+   /* errno of the last wl_display error */
int last_error;
+
+   /* When display gets an error event from some object, it stores
+* information about it here, so that client can get this
+* information afterwards */
+   struct {
+   /* Code of the error. It can be compared to
+* the interface's errors enumeration. */
+   uint32_t code;
+   /* interface (protocol) in which the error occurred */
+   const struct wl_interface *interface;
+   /* id of the proxy that caused the error. There's no warranty
+* that the proxy is still valid. It's up to client how it will
+* use it */
+   uint32_t id;
+   } protocol_error;
int fd;
pthread_t display_thread;
struct wl_map objects;
@@ -96,6 +113,14 @@ struct wl_display {
 
 static int debug_client = 0;
 
+/**
+ * This function is called for local errors (no memory, server hung up)
+ *
+ * \param display
+ * \param errorerror value (EINVAL, EFAULT, ...)
+ *
+ * \note this function is called with display mutex locked
+ */
 static void
 display_fatal_error(struct wl_display *display, int error)
 {
@@ -105,7 +130,7 @@ display_fatal_error(struct wl_display *display, int error)
return;
 
if (!error)
-   error = 1;
+   error = EFAULT;
 
display->last_error = error;
 
@@ -113,11 +138,56 @@ display_fatal_error(struct wl_display *display, int error)
pthread_cond_broadcast(&iter->cond);
 }
 
+/**
+ * This function is called for error events
+ * and idicates that in some object occured an error.
+ * Difference between this function and display_fatal_error()
+ * is that this one handles errors that will come in wire, whereas
+ * display_fatal_error() is called for local errors.
+ *
+ * \param display
+ * \param codeerror code
+ * \param id  id of the object that generated the error
+ * \param intfprotocol interface
+ */
 static void
-wl_display_fatal_error(struct wl_display *display, int error)
+display_protocol_error(struct wl_display *display, uint32_t code,
+  uint32_t id, const struct wl_interface *intf)
 {
+   struct wl_event_queue *iter;
+   int err;
+
+   if (display->last_error)
+   return;
+
+   /* set correct errno */
+   if (wl_interface_equal(intf, &wl_display_interface)) {
+   switch (code) {
+   case WL_DISPLAY_ERROR_INVALID_OBJECT:
+   case WL_DISPLAY_ERROR_INVALID_METHOD:
+   err = EINVAL;
+   break;
+   case WL_DISPLAY_ERROR_NO_MEMORY:
+   err = ENOMEM;
+   break;
+   default:
+   err = EFAULT;
+   }
+   } else {
+   err = EPROTO;
+   }
+
pthread_mutex_lock(&display->mutex);
-   display_fatal_error(display, error);
+
+   display->last_error = err;
+
+   display->protocol_error.code = code;
+   display->protocol_error.id = id;
+   display->protocol_error.interface = intf;
+
+   wl_list_for_each(iter, &display->event_queue_list, link)
+   pthread_cond_broadcast(&iter->cond);
+
pthread_mutex_unlock(&display->mutex);
 }
 
@@ -579,25 +649,12 @@ display_handle_error(void *data,
 uint32_t code, const char *message)
 {
struct wl_proxy *proxy = object;
-   int err;
 
wl_log("%s@%u: error %d: %s\n",
   proxy->object.interface->name, proxy->object.id, code, message);
 
-   switch (code) {
-   case WL_DISPLAY_ERROR_INVALID_OBJECT:
-   case WL_DISPLAY_ERROR_INVALID_METHOD:
-   

Re: [PATCH v3] client: extend error handling

2014-05-05 Thread Pekka Paalanen
On Wed, 30 Apr 2014 10:11:01 +0200
Marek Chalupa  wrote:

> When an error occurs, wl_display_get_error() does not
> provide any way of getting know if it was a local error or if it was
> an error event, respectively what object caused the error and what
> the error was.
> 
> This patch introduces a new function wl_display_get_protocol_error()
> which will return error code, interface and id of the object that
> generated the error.
> wl_display_get_error() will work the same way as before.
> 
> wl_display_get_protocol_error() DOES NOT indicate that a non-protocol
> error happened. It returns valid information only in that case that
> (protocol) error occurred, so it should be used after calling
> wl_display_get_error() with positive result.
> 
> Thanks to Pekka Paalanen  for pointing out
> issues in the first versions of this patch.
> ---
>  src/wayland-client.c | 138 
> ---
>  src/wayland-client.h |   3 ++
>  2 files changed, 123 insertions(+), 18 deletions(-)
> 
> diff --git a/src/wayland-client.c b/src/wayland-client.c
> index bd40313..8dd8804 100644
> --- a/src/wayland-client.c
> +++ b/src/wayland-client.c
> @@ -78,7 +78,24 @@ struct wl_event_queue {
>  struct wl_display {
>   struct wl_proxy proxy;
>   struct wl_connection *connection;
> +
> + /* errno of the last wl_display error */
>   int last_error;
> +
> + /* When display gets an error event from some object, it stores
> +  * information about it here, so that client can get this
> +  * information afterwards */
> + struct {
> + /* Code of the error. It can be compared to
> +  * the interface's errors enumeration. */
> + int code;

I just checked in wl_display::error specification, and the type of the
error code is uint32_t.

> + /* interface (protocol) in which the error occurred */
> + const struct wl_interface *interface;
> + /* id of the proxy that caused the error. There's no warranty
> +  * that the proxy is still valid. It's up to client how it will
> +  * use it */
> + uint32_t id;
> + } protocol_error;
>   int fd;
>   pthread_t display_thread;
>   struct wl_map objects;
> @@ -96,6 +113,14 @@ struct wl_display {
>  
>  static int debug_client = 0;
>  
> +/**
> + * This function is called for local errors (no memory, server hung up)
> + *
> + * \param display
> + * \param errorerror value (EINVAL, EFAULT, ...)
> + *
> + * \note this function is called with display mutex locked
> + */
>  static void
>  display_fatal_error(struct wl_display *display, int error)
>  {
> @@ -105,7 +130,7 @@ display_fatal_error(struct wl_display *display, int error)
>   return;
>  
>   if (!error)
> - error = 1;
> + error = EFAULT;
>  
>   display->last_error = error;
>  
> @@ -113,11 +138,56 @@ display_fatal_error(struct wl_display *display, int 
> error)
>   pthread_cond_broadcast(&iter->cond);
>  }
>  
> +/**
> + * This function is called for error events
> + * and idicates that in some object occured an error.
> + * Difference between this function and display_fatal_error()
> + * is that this one handles errors that will come in wire, whereas
> + * display_fatal_error() is called for local errors.
> + *
> + * \param display
> + * \param codeerror code
> + * \param id  id of the object that generated the error
> + * \param intfprotocol interface
> + */
>  static void
> -wl_display_fatal_error(struct wl_display *display, int error)
> +display_protocol_error(struct wl_display *display, int code,
> +unsigned int id, const struct wl_interface *intf)
>  {
> + struct wl_event_queue *iter;
> + int err;
> +
> + if (display->last_error)
> + return;
> +
> + /* set correct errno */
> + if (wl_interface_equal(intf, &wl_display_interface)) {
> + switch (code) {
> + case WL_DISPLAY_ERROR_INVALID_OBJECT:
> + case WL_DISPLAY_ERROR_INVALID_METHOD:
> + err = EINVAL;
> + break;
> + case WL_DISPLAY_ERROR_NO_MEMORY:
> + err = ENOMEM;
> + break;
> + default:
> + err = EFAULT;
> + }
> + } else {
> + err = EPROTO;
> + }
> +
>   pthread_mutex_lock(&display->mutex);
> - display_fatal_error(display, error);
> +
> + display->last_error = err;
> +
> + display->protocol_error.code = code;
> + display->protocol_error.id = id;
> + display->protocol_error.interface = intf;
> +
> + wl_list_for_each(iter, &display->event_queue_list, link)
> + pthread_cond_broadcast(&iter->cond);
> +
>   pthread_mutex_unlock(&display->mutex);
>  }
>  
> @@ -579,25 +649,12 @@ display_handle_error(void *data,
>uint32_t code, const char *mes

[PATCH v3] client: extend error handling

2014-04-30 Thread Marek Chalupa
When an error occurs, wl_display_get_error() does not
provide any way of getting know if it was a local error or if it was
an error event, respectively what object caused the error and what
the error was.

This patch introduces a new function wl_display_get_protocol_error()
which will return error code, interface and id of the object that
generated the error.
wl_display_get_error() will work the same way as before.

wl_display_get_protocol_error() DOES NOT indicate that a non-protocol
error happened. It returns valid information only in that case that
(protocol) error occurred, so it should be used after calling
wl_display_get_error() with positive result.

Thanks to Pekka Paalanen  for pointing out
issues in the first versions of this patch.
---
 src/wayland-client.c | 138 ---
 src/wayland-client.h |   3 ++
 2 files changed, 123 insertions(+), 18 deletions(-)

diff --git a/src/wayland-client.c b/src/wayland-client.c
index bd40313..8dd8804 100644
--- a/src/wayland-client.c
+++ b/src/wayland-client.c
@@ -78,7 +78,24 @@ struct wl_event_queue {
 struct wl_display {
struct wl_proxy proxy;
struct wl_connection *connection;
+
+   /* errno of the last wl_display error */
int last_error;
+
+   /* When display gets an error event from some object, it stores
+* information about it here, so that client can get this
+* information afterwards */
+   struct {
+   /* Code of the error. It can be compared to
+* the interface's errors enumeration. */
+   int code;
+   /* interface (protocol) in which the error occurred */
+   const struct wl_interface *interface;
+   /* id of the proxy that caused the error. There's no warranty
+* that the proxy is still valid. It's up to client how it will
+* use it */
+   uint32_t id;
+   } protocol_error;
int fd;
pthread_t display_thread;
struct wl_map objects;
@@ -96,6 +113,14 @@ struct wl_display {
 
 static int debug_client = 0;
 
+/**
+ * This function is called for local errors (no memory, server hung up)
+ *
+ * \param display
+ * \param errorerror value (EINVAL, EFAULT, ...)
+ *
+ * \note this function is called with display mutex locked
+ */
 static void
 display_fatal_error(struct wl_display *display, int error)
 {
@@ -105,7 +130,7 @@ display_fatal_error(struct wl_display *display, int error)
return;
 
if (!error)
-   error = 1;
+   error = EFAULT;
 
display->last_error = error;
 
@@ -113,11 +138,56 @@ display_fatal_error(struct wl_display *display, int error)
pthread_cond_broadcast(&iter->cond);
 }
 
+/**
+ * This function is called for error events
+ * and idicates that in some object occured an error.
+ * Difference between this function and display_fatal_error()
+ * is that this one handles errors that will come in wire, whereas
+ * display_fatal_error() is called for local errors.
+ *
+ * \param display
+ * \param codeerror code
+ * \param id  id of the object that generated the error
+ * \param intfprotocol interface
+ */
 static void
-wl_display_fatal_error(struct wl_display *display, int error)
+display_protocol_error(struct wl_display *display, int code,
+  unsigned int id, const struct wl_interface *intf)
 {
+   struct wl_event_queue *iter;
+   int err;
+
+   if (display->last_error)
+   return;
+
+   /* set correct errno */
+   if (wl_interface_equal(intf, &wl_display_interface)) {
+   switch (code) {
+   case WL_DISPLAY_ERROR_INVALID_OBJECT:
+   case WL_DISPLAY_ERROR_INVALID_METHOD:
+   err = EINVAL;
+   break;
+   case WL_DISPLAY_ERROR_NO_MEMORY:
+   err = ENOMEM;
+   break;
+   default:
+   err = EFAULT;
+   }
+   } else {
+   err = EPROTO;
+   }
+
pthread_mutex_lock(&display->mutex);
-   display_fatal_error(display, error);
+
+   display->last_error = err;
+
+   display->protocol_error.code = code;
+   display->protocol_error.id = id;
+   display->protocol_error.interface = intf;
+
+   wl_list_for_each(iter, &display->event_queue_list, link)
+   pthread_cond_broadcast(&iter->cond);
+
pthread_mutex_unlock(&display->mutex);
 }
 
@@ -579,25 +649,12 @@ display_handle_error(void *data,
 uint32_t code, const char *message)
 {
struct wl_proxy *proxy = object;
-   int err;
 
wl_log("%s@%u: error %d: %s\n",
   proxy->object.interface->name, proxy->object.id, code, message);
 
-   switch (code) {
-   case WL_DISPLAY_ERROR_INVALID_OBJECT:
-   case WL_DISPLAY_ERROR_INVALID_METHOD:
-