aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBartosz Golaszewski <bartosz.golaszewski@linaro.org>2023-04-20 09:32:56 +0200
committerBartosz Golaszewski <bartosz.golaszewski@linaro.org>2023-04-20 09:32:56 +0200
commit0fdc1a11c9cc05ea281d47235ecf9d5bee2ff505 (patch)
tree034e418810afa576d204164b4244ecfd55b15337
parentb9f5d29950a41d2a3089e8e21838822b751f937f (diff)
downloadlibgpiod-0fdc1a11c9cc05ea281d47235ecf9d5bee2ff505.tar.gz
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 <bartosz.golaszewski@linaro.org>
-rw-r--r--tests/gpiod-test-sim.c105
1 files changed, 54 insertions, 51 deletions
diff --git a/tests/gpiod-test-sim.c b/tests/gpiod-test-sim.c
index 161a09f7..ac6c71a8 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 *