mirror of
https://gitlab.freedesktop.org/wayland/wayland.git
synced 2025-10-29 05:40:16 -04:00
client: extend error handling
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. [Pekka Paalanen] Applied another hunk of Bryce's comments to docs, added libtool version bump. Reviewed-by: Pekka Paalanen <ppaalanen@gmail.com> Reviewed-by: Bryce Harrington <b.harrington@samsung.com>
This commit is contained in:
parent
567977815a
commit
886b09c9a3
3 changed files with 123 additions and 19 deletions
|
|
@ -51,7 +51,7 @@ nodist_libwayland_server_la_SOURCES = \
|
||||||
|
|
||||||
libwayland_client_la_CFLAGS = $(FFI_CFLAGS) $(GCC_CFLAGS) -pthread
|
libwayland_client_la_CFLAGS = $(FFI_CFLAGS) $(GCC_CFLAGS) -pthread
|
||||||
libwayland_client_la_LIBADD = $(FFI_LIBS) libwayland-util.la -lrt -lm
|
libwayland_client_la_LIBADD = $(FFI_LIBS) libwayland-util.la -lrt -lm
|
||||||
libwayland_client_la_LDFLAGS = -version-info 2:0:2
|
libwayland_client_la_LDFLAGS = -version-info 3:0:3
|
||||||
libwayland_client_la_SOURCES = \
|
libwayland_client_la_SOURCES = \
|
||||||
src/wayland-client.c
|
src/wayland-client.c
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -78,7 +78,24 @@ struct wl_event_queue {
|
||||||
struct wl_display {
|
struct wl_display {
|
||||||
struct wl_proxy proxy;
|
struct wl_proxy proxy;
|
||||||
struct wl_connection *connection;
|
struct wl_connection *connection;
|
||||||
|
|
||||||
|
/* errno of the last wl_display error */
|
||||||
int last_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;
|
int fd;
|
||||||
pthread_t display_thread;
|
pthread_t display_thread;
|
||||||
struct wl_map objects;
|
struct wl_map objects;
|
||||||
|
|
@ -96,6 +113,14 @@ struct wl_display {
|
||||||
|
|
||||||
static int debug_client = 0;
|
static int debug_client = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This function is called for local errors (no memory, server hung up)
|
||||||
|
*
|
||||||
|
* \param display
|
||||||
|
* \param error error value (EINVAL, EFAULT, ...)
|
||||||
|
*
|
||||||
|
* \note this function is called with display mutex locked
|
||||||
|
*/
|
||||||
static void
|
static void
|
||||||
display_fatal_error(struct wl_display *display, int error)
|
display_fatal_error(struct wl_display *display, int error)
|
||||||
{
|
{
|
||||||
|
|
@ -105,7 +130,7 @@ display_fatal_error(struct wl_display *display, int error)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!error)
|
if (!error)
|
||||||
error = 1;
|
error = EFAULT;
|
||||||
|
|
||||||
display->last_error = error;
|
display->last_error = error;
|
||||||
|
|
||||||
|
|
@ -113,11 +138,56 @@ display_fatal_error(struct wl_display *display, int error)
|
||||||
pthread_cond_broadcast(&iter->cond);
|
pthread_cond_broadcast(&iter->cond);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This function is called for error events
|
||||||
|
* and indicates that in some object an error occured.
|
||||||
|
* Difference between this function and display_fatal_error()
|
||||||
|
* is that this one handles errors that will come by wire,
|
||||||
|
* whereas display_fatal_error() is called for local errors.
|
||||||
|
*
|
||||||
|
* \param display
|
||||||
|
* \param code error code
|
||||||
|
* \param id id of the object that generated the error
|
||||||
|
* \param intf protocol interface
|
||||||
|
*/
|
||||||
static void
|
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);
|
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);
|
pthread_mutex_unlock(&display->mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -579,25 +649,12 @@ display_handle_error(void *data,
|
||||||
uint32_t code, const char *message)
|
uint32_t code, const char *message)
|
||||||
{
|
{
|
||||||
struct wl_proxy *proxy = object;
|
struct wl_proxy *proxy = object;
|
||||||
int err;
|
|
||||||
|
|
||||||
wl_log("%s@%u: error %d: %s\n",
|
wl_log("%s@%u: error %d: %s\n",
|
||||||
proxy->object.interface->name, proxy->object.id, code, message);
|
proxy->object.interface->name, proxy->object.id, code, message);
|
||||||
|
|
||||||
switch (code) {
|
display_protocol_error(display, code, proxy->object.id,
|
||||||
case WL_DISPLAY_ERROR_INVALID_OBJECT:
|
proxy->object.interface);
|
||||||
case WL_DISPLAY_ERROR_INVALID_METHOD:
|
|
||||||
err = EINVAL;
|
|
||||||
break;
|
|
||||||
case WL_DISPLAY_ERROR_NO_MEMORY:
|
|
||||||
err = ENOMEM;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
err = EFAULT;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
wl_display_fatal_error(display, err);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
@ -1486,6 +1543,50 @@ wl_display_get_error(struct wl_display *display)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the information about a protocol error:
|
||||||
|
*
|
||||||
|
* \param display The Wayland display
|
||||||
|
* \param interface if not NULL, stores the interface where the error occurred
|
||||||
|
* \param id if not NULL, stores the object id that generated
|
||||||
|
* the error. There's no guarantee the object is
|
||||||
|
* still valid; the client must know if it deleted the object.
|
||||||
|
* \return The error code as defined in the interface specification.
|
||||||
|
*
|
||||||
|
* \code
|
||||||
|
* int err = wl_display_get_error(display);
|
||||||
|
*
|
||||||
|
* if (err == EPROTO) {
|
||||||
|
* code = wl_display_get_protocol_error(display, &interface, &id);
|
||||||
|
* handle_error(code, interface, id);
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* ...
|
||||||
|
*
|
||||||
|
* \endcode
|
||||||
|
*/
|
||||||
|
WL_EXPORT uint32_t
|
||||||
|
wl_display_get_protocol_error(struct wl_display *display,
|
||||||
|
const struct wl_interface **interface,
|
||||||
|
uint32_t *id)
|
||||||
|
{
|
||||||
|
uint32_t ret;
|
||||||
|
|
||||||
|
pthread_mutex_lock(&display->mutex);
|
||||||
|
|
||||||
|
ret = display->protocol_error.code;
|
||||||
|
|
||||||
|
if (interface)
|
||||||
|
*interface = display->protocol_error.interface;
|
||||||
|
if (id)
|
||||||
|
*id = display->protocol_error.id;
|
||||||
|
|
||||||
|
pthread_mutex_unlock(&display->mutex);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/** Send all buffered requests on the display to the server
|
/** Send all buffered requests on the display to the server
|
||||||
*
|
*
|
||||||
* \param display The display context object
|
* \param display The display context object
|
||||||
|
|
|
||||||
|
|
@ -161,6 +161,9 @@ int wl_display_dispatch_queue_pending(struct wl_display *display,
|
||||||
struct wl_event_queue *queue);
|
struct wl_event_queue *queue);
|
||||||
int wl_display_dispatch_pending(struct wl_display *display);
|
int wl_display_dispatch_pending(struct wl_display *display);
|
||||||
int wl_display_get_error(struct wl_display *display);
|
int wl_display_get_error(struct wl_display *display);
|
||||||
|
uint32_t wl_display_get_protocol_error(struct wl_display *display,
|
||||||
|
const struct wl_interface **interface,
|
||||||
|
uint32_t *id);
|
||||||
|
|
||||||
int wl_display_flush(struct wl_display *display);
|
int wl_display_flush(struct wl_display *display);
|
||||||
int wl_display_roundtrip(struct wl_display *display);
|
int wl_display_roundtrip(struct wl_display *display);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue