From e6c3dd24a6346b9c24bf5e2e6289e04a726ee334 Mon Sep 17 00:00:00 2001 From: Alex Tereschenko Date: Fri, 2 Oct 2015 23:42:20 +0200 Subject: [PATCH] gpio.c: Added ISR thread termination flag Also modified ISR handler logic to account for the flag. This fixes isrExit() deadlock in Python interactive mode and prevents a more generic problem of a spurious ISR call after mraa_gpio_isr_exit() is run. Closes #268. Signed-off-by: Alex Tereschenko Signed-off-by: Brendan Le Foll --- include/mraa_internal_types.h | 1 + src/gpio/gpio.c | 8 ++++++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/include/mraa_internal_types.h b/include/mraa_internal_types.h index cdb5950..c119c79 100644 --- a/include/mraa_internal_types.h +++ b/include/mraa_internal_types.h @@ -47,6 +47,7 @@ struct _gpio { void *isr_args; /**< args return when interupt service request triggered */ pthread_t thread_id; /**< the isr handler thread id */ int isr_value_fp; /**< the isr file pointer on the value */ + mraa_boolean_t isr_thread_terminating; /**< is the isr thread being terminated? */ mraa_boolean_t owner; /**< If this context originally exported the pin */ mraa_result_t (*mmap_write) (mraa_gpio_context dev, int value); int (*mmap_read) (mraa_gpio_context dev); diff --git a/src/gpio/gpio.c b/src/gpio/gpio.c index ae5062b..ffaac30 100644 --- a/src/gpio/gpio.c +++ b/src/gpio/gpio.c @@ -87,6 +87,7 @@ mraa_gpio_init_internal(mraa_adv_func_t* func_table, int pin) dev->value_fp = -1; dev->isr_value_fp = -1; + dev->isr_thread_terminating = 0; dev->phy_pin = -1; // then check to make sure the pin is exported. @@ -229,7 +230,7 @@ mraa_gpio_interrupt_handler(void* arg) for (;;) { ret = mraa_gpio_wait_interrupt(dev->isr_value_fp); - if (ret == MRAA_SUCCESS) { + if (ret == MRAA_SUCCESS && !dev->isr_thread_terminating) { pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); #ifdef SWIGPYTHON // In order to call a python object (all python functions are objects) we @@ -258,7 +259,7 @@ mraa_gpio_interrupt_handler(void* arg) #endif pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); } else { - // we must have got an error code so die nicely + // we must have got an error code or exit request so die nicely pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); close(dev->isr_value_fp); dev->isr_value_fp = -1; @@ -344,6 +345,8 @@ mraa_gpio_isr_exit(mraa_gpio_context dev) if (dev->thread_id == 0 && dev->isr_value_fp == -1) { return ret; } + // mark the beginning of the thread termination process for interested parties + dev->isr_thread_terminating = 1; // stop isr being useful ret = mraa_gpio_edge_mode(dev, MRAA_GPIO_EDGE_NONE); @@ -364,6 +367,7 @@ mraa_gpio_isr_exit(mraa_gpio_context dev) // assume our thread will exit either way we just lost it's handle dev->thread_id = 0; dev->isr_value_fp = -1; + dev->isr_thread_terminating = 0; return ret; }