gpio.c: Added ISR thread termination flag
authorAlex Tereschenko <alext.mkrs@gmail.com>
Fri, 2 Oct 2015 21:42:20 +0000 (23:42 +0200)
committerBrendan Le Foll <brendan.le.foll@intel.com>
Tue, 6 Oct 2015 13:40:57 +0000 (14:40 +0100)
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 <alext.mkrs@gmail.com>
Signed-off-by: Brendan Le Foll <brendan.le.foll@intel.com>
include/mraa_internal_types.h
src/gpio/gpio.c

index cdb5950..c119c79 100644 (file)
@@ -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);
index ae5062b..ffaac30 100644 (file)
@@ -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;
 }