From: Bartosz Golaszewski Date: Thu, 20 Apr 2023 07:32:56 +0000 (+0200) Subject: tests: don't segfault if gpio-sim is unavailable X-Git-Url: http://git.maquefel.me/?a=commitdiff_plain;h=0fdc1a11c9cc05ea281d47235ecf9d5bee2ff505;p=qemu-gpiodev%2Flibgpiod.git tests: don't segfault if gpio-sim is unavailable The GLib wrapper for libgpiosim tries to create the gpiosim context and bank objects in the class's init() function but the constructed() callback doesn't check if that operation succeeded, leading to a crash when it dereferences the bank pointer. As init() should only perform operations that cannot fail, let's move all the gpiosim initialization code to constructed() and bail-out of it if any of the steps fails. Signed-off-by: Bartosz Golaszewski --- diff --git a/tests/gpiod-test-sim.c b/tests/gpiod-test-sim.c index 161a09f..ac6c71a 100644 --- a/tests/gpiod-test-sim.c +++ b/tests/gpiod-test-sim.c @@ -180,11 +180,53 @@ static gboolean g_gpiosim_chip_enable(GPIOSimChip *self) return TRUE; } +static gboolean g_gpiosim_ctx_init(GError **err) +{ + sim_ctx = gpiosim_ctx_new(); + if (!sim_ctx) { + g_set_error(err, G_GPIOSIM_ERROR, + G_GPIOSIM_ERR_CTX_INIT_FAILED, + "Unable to initialize libgpiosim: %s", + g_strerror(errno)); + return FALSE; + } + + atexit(g_gpiosim_ctx_unref); + + return TRUE; +} + static void g_gpiosim_chip_constructed(GObject *obj) { GPIOSimChip *self = G_GPIOSIM_CHIP(obj); + struct gpiosim_dev *dev; gboolean ret; + if (!sim_ctx) { + ret = g_gpiosim_ctx_init(&self->construct_err); + if (!ret) + return; + } + + dev = gpiosim_dev_new(sim_ctx); + if (!dev) { + g_set_error(&self->construct_err, G_GPIOSIM_ERROR, + G_GPIOSIM_ERR_CHIP_INIT_FAILED, + "Unable to instantiate new GPIO device: %s", + g_strerror(errno)); + return; + } + + self->bank = gpiosim_bank_new(dev); + gpiosim_dev_unref(dev); + if (!self->bank) { + g_set_error(&self->construct_err, G_GPIOSIM_ERROR, + G_GPIOSIM_ERR_CHIP_INIT_FAILED, + "Unable to instantiate new GPIO bank: %s", + g_strerror(errno)); + return; + } + ret = g_gpiosim_chip_apply_properties(self); if (!ret) return; @@ -263,16 +305,12 @@ static void g_gpiosim_chip_dispose(GObject *obj) G_OBJECT_CLASS(g_gpiosim_chip_parent_class)->dispose(obj); } -static void g_gpiosim_chip_finalize(GObject *obj) +static void g_gpiosim_disable_and_cleanup(struct gpiosim_bank *bank) { - GPIOSimChip *self = G_GPIOSIM_CHIP(obj); struct gpiosim_dev *dev; gint ret; - g_clear_error(&self->construct_err); - g_clear_pointer(&self->label, g_free); - - dev = gpiosim_bank_get_dev(self->bank); + dev = gpiosim_bank_get_dev(bank); if (gpiosim_dev_is_live(dev)) { ret = gpiosim_dev_disable(dev); @@ -282,7 +320,16 @@ static void g_gpiosim_chip_finalize(GObject *obj) } gpiosim_dev_unref(dev); - gpiosim_bank_unref(self->bank); + gpiosim_bank_unref(bank); +} + +static void g_gpiosim_chip_finalize(GObject *obj) +{ + GPIOSimChip *self = G_GPIOSIM_CHIP(obj); + + g_clear_error(&self->construct_err); + g_clear_pointer(&self->label, g_free); + g_clear_pointer(&self->bank, g_gpiosim_disable_and_cleanup); G_OBJECT_CLASS(g_gpiosim_chip_parent_class)->finalize(obj); } @@ -340,57 +387,13 @@ static void g_gpiosim_chip_class_init(GPIOSimChipClass *chip_class) G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY)); } -static gboolean g_gpiosim_ctx_init(GError **err) -{ - sim_ctx = gpiosim_ctx_new(); - if (!sim_ctx) { - g_set_error(err, G_GPIOSIM_ERROR, - G_GPIOSIM_ERR_CTX_INIT_FAILED, - "Unable to initialize libgpiosim: %s", - g_strerror(errno)); - return FALSE; - } - - atexit(g_gpiosim_ctx_unref); - - return TRUE; -} - static void g_gpiosim_chip_init(GPIOSimChip *self) { - struct gpiosim_dev *dev; - int ret; - self->construct_err = NULL; self->num_lines = 1; self->label = NULL; self->line_names = NULL; self->hogs = NULL; - - if (!sim_ctx) { - ret = g_gpiosim_ctx_init(&self->construct_err); - if (!ret) - return; - } - - dev = gpiosim_dev_new(sim_ctx); - if (!dev) { - g_set_error(&self->construct_err, G_GPIOSIM_ERROR, - G_GPIOSIM_ERR_CHIP_INIT_FAILED, - "Unable to instantiate new GPIO device: %s", - g_strerror(errno)); - return; - } - - self->bank = gpiosim_bank_new(dev); - gpiosim_dev_unref(dev); - if (!self->bank) { - g_set_error(&self->construct_err, G_GPIOSIM_ERROR, - G_GPIOSIM_ERR_CHIP_INIT_FAILED, - "Unable to instantiate new GPIO bank: %s", - g_strerror(errno)); - return; - } } static const gchar *