1
0
Fork 0

Gracefully exit with failure if backend creation failed

Instead of continuing eventually crashing with a segmentation fault due
to a missing renderer, make MetaBackend an GInitable, and gracefully
handle the failure to fully create the backend with an EXIT_FAILURE.

https://bugzilla.gnome.org/show_bug.cgi?id=769036
This commit is contained in:
Jonas Ådahl 2016-07-23 10:26:39 +08:00
parent cd225c4e19
commit 820a6ab406

View file

@ -28,6 +28,7 @@
#include <clutter/clutter-mutter.h> #include <clutter/clutter-mutter.h>
#include <meta/meta-backend.h> #include <meta/meta-backend.h>
#include <meta/main.h>
#include "meta-backend-private.h" #include "meta-backend-private.h"
#include "meta-input-settings-private.h" #include "meta-input-settings-private.h"
@ -72,7 +73,13 @@ struct _MetaBackendPrivate
}; };
typedef struct _MetaBackendPrivate MetaBackendPrivate; typedef struct _MetaBackendPrivate MetaBackendPrivate;
G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (MetaBackend, meta_backend, G_TYPE_OBJECT); static void
initable_iface_init (GInitableIface *initable_iface);
G_DEFINE_ABSTRACT_TYPE_WITH_CODE (MetaBackend, meta_backend, G_TYPE_OBJECT,
G_ADD_PRIVATE (MetaBackend)
G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE,
initable_iface_init));
static void static void
meta_backend_finalize (GObject *object) meta_backend_finalize (GObject *object)
@ -362,21 +369,11 @@ meta_backend_real_get_relative_motion_deltas (MetaBackend *backend,
return FALSE; return FALSE;
} }
static void
meta_backend_constructed (GObject *object)
{
MetaBackend *backend = META_BACKEND (object);
MetaBackendPrivate *priv = meta_backend_get_instance_private (backend);
priv->renderer = META_BACKEND_GET_CLASS (backend)->create_renderer (backend);
}
static void static void
meta_backend_class_init (MetaBackendClass *klass) meta_backend_class_init (MetaBackendClass *klass)
{ {
GObjectClass *object_class = G_OBJECT_CLASS (klass); GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->constructed = meta_backend_constructed;
object_class->finalize = meta_backend_finalize; object_class->finalize = meta_backend_finalize;
klass->post_init = meta_backend_real_post_init; klass->post_init = meta_backend_real_post_init;
@ -406,6 +403,32 @@ meta_backend_class_init (MetaBackendClass *klass)
G_TYPE_NONE, 1, G_TYPE_INT); G_TYPE_NONE, 1, G_TYPE_INT);
} }
static gboolean
meta_backend_initable_init (GInitable *initable,
GCancellable *cancellable,
GError **error)
{
MetaBackend *backend = META_BACKEND (initable);
MetaBackendPrivate *priv = meta_backend_get_instance_private (backend);
priv->renderer = META_BACKEND_GET_CLASS (backend)->create_renderer (backend);
if (!priv->renderer)
{
g_set_error (error, G_IO_ERROR,
G_IO_ERROR_FAILED,
"Failed to create MetaRenderer");
return FALSE;
}
return TRUE;
}
static void
initable_iface_init (GInitableIface *initable_iface)
{
initable_iface->init = meta_backend_initable_init;
}
static void static void
meta_backend_init (MetaBackend *backend) meta_backend_init (MetaBackend *backend)
{ {
@ -696,6 +719,8 @@ void
meta_init_backend (MetaBackendType backend_type) meta_init_backend (MetaBackendType backend_type)
{ {
GType type; GType type;
MetaBackend *backend;
GError *error = NULL;
switch (backend_type) switch (backend_type)
{ {
@ -715,7 +740,12 @@ meta_init_backend (MetaBackendType backend_type)
/* meta_backend_init() above install the backend globally so /* meta_backend_init() above install the backend globally so
* so meta_get_backend() works even during initialization. */ * so meta_get_backend() works even during initialization. */
g_object_new (type, NULL); backend = g_object_new (type, NULL);
if (!g_initable_init (G_INITABLE (backend), NULL, &error))
{
g_warning ("Failed to create backend: %s", error->message);
meta_exit (META_EXIT_ERROR);
}
} }
/** /**