static void* mraa_gpio_interrupt_handler(void* arg) { mraa_gpio_context dev = (mraa_gpio_context) arg; mraa_result_t ret; // open gpio value with open(3) char bu[MAX_SIZE]; sprintf(bu, SYSFS_CLASS_GPIO "/gpio%d/value", dev->pin); int fp = open(bu, O_RDONLY); if (fp < 0) { syslog(LOG_ERR, "gpio: failed to open gpio%d/value", dev->pin); return NULL; } dev->isr_value_fp = fp; for (;;) { ret = mraa_gpio_wait_interrupt(dev->isr_value_fp); if (ret == MRAA_SUCCESS) { pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); #ifdef SWIGPYTHON // In order to call a python object (all python functions are objects) we // need to aquire the GIL (Global Interpreter Lock). This may not always be // nessecary but especially if doing IO (like print()) python will segfault // if we do not hold a lock on the GIL PyGILState_STATE gilstate = PyGILState_Ensure(); PyObject *arglist; PyObject *ret; arglist = Py_BuildValue("(i)", dev->isr_args); if (arglist == NULL) { syslog(LOG_ERR, "gpio: Py_BuildValue NULL"); } else { ret = PyEval_CallObject((PyObject*)dev->isr, arglist); if (ret == NULL) { syslog(LOG_ERR, "gpio: PyEval_CallObject failed"); } else { Py_DECREF(ret); } Py_DECREF(arglist); } PyGILState_Release (gilstate); #else dev->isr(dev->isr_args); #endif pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); } else { // we must have got an error code so die nicely pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); close(dev->isr_value_fp); dev->isr_value_fp = -1; return NULL; } } }
static void* mraa_gpio_interrupt_handler(void* arg) { mraa_gpio_context dev = (mraa_gpio_context) arg; if (IS_FUNC_DEFINED(dev, gpio_interrupt_handler_replace)) return dev->advance_func->gpio_interrupt_handler_replace(dev); mraa_result_t ret; // open gpio value with open(3) char bu[MAX_SIZE]; sprintf(bu, SYSFS_CLASS_GPIO "/gpio%d/value", dev->pin); int fp = open(bu, O_RDONLY); if (fp < 0) { syslog(LOG_ERR, "gpio: failed to open gpio%d/value", dev->pin); return NULL; } #ifndef HAVE_PTHREAD_CANCEL if (pipe(dev->isr_control_pipe)) { syslog(LOG_ERR, "gpio: failed to create isr control pipe"); close(fp); return NULL; } #endif dev->isr_value_fp = fp; #if defined(SWIGJAVA) || defined(JAVACALLBACK) JNIEnv *jenv; if(dev->isr == mraa_java_isr_callback) { jint err = (*globVM)->AttachCurrentThreadAsDaemon(globVM, (void **)&jenv, NULL); if (err != JNI_OK) { close(dev->isr_value_fp); dev->isr_value_fp = -1; return NULL; } pthread_once(&env_key_init, make_env_key); pthread_setspecific(env_key, jenv); } #endif for (;;) { ret = mraa_gpio_wait_interrupt(dev->isr_value_fp #ifndef HAVE_PTHREAD_CANCEL , dev->isr_control_pipe[0] #endif ); if (ret == MRAA_SUCCESS && !dev->isr_thread_terminating) { #ifdef HAVE_PTHREAD_CANCEL pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); #endif #ifdef SWIGPYTHON // In order to call a python object (all python functions are objects) we // need to aquire the GIL (Global Interpreter Lock). This may not always be // necessary but especially if doing IO (like print()) python will segfault // if we do not hold a lock on the GIL PyGILState_STATE gilstate = PyGILState_Ensure(); PyObject* arglist; PyObject* ret; arglist = Py_BuildValue("(O)", dev->isr_args); if (arglist == NULL) { syslog(LOG_ERR, "gpio: Py_BuildValue NULL"); } else { ret = PyEval_CallObject((PyObject*) dev->isr, arglist); if (ret == NULL) { syslog(LOG_ERR, "gpio: PyEval_CallObject failed"); PyObject *pvalue, *ptype, *ptraceback; PyObject *pvalue_pystr, *ptype_pystr, *ptraceback_pystr; char *pvalue_cstr, *ptype_cstr, *ptraceback_cstr; PyErr_Fetch(&pvalue, &ptype, &ptraceback); pvalue_pystr = PyObject_Str(pvalue); ptype_pystr = PyObject_Str(ptype); ptraceback_pystr = PyObject_Str(ptraceback); // Python2 #if PY_VERSION_HEX < 0x03000000 pvalue_cstr = PyString_AsString(pvalue_pystr); ptype_cstr = PyString_AsString(ptype_pystr); ptraceback_cstr = PyString_AsString(ptraceback_pystr); // Python 3 and up #elif PY_VERSION_HEX >= 0x03000000 // In Python 3 we need one extra conversion PyObject *pvalue_ustr, *ptype_ustr, *ptraceback_ustr; pvalue_ustr = PyUnicode_AsUTF8String(pvalue_pystr); pvalue_cstr = PyBytes_AsString(pvalue_ustr); ptype_ustr = PyUnicode_AsUTF8String(ptype_pystr); ptype_cstr = PyBytes_AsString(ptype_ustr); ptraceback_ustr = PyUnicode_AsUTF8String(ptraceback_pystr); ptraceback_cstr = PyBytes_AsString(ptraceback_ustr); #endif // PY_VERSION_HEX syslog(LOG_ERR, "gpio: the error was %s:%s:%s", pvalue_cstr, ptype_cstr, ptraceback_cstr ); Py_XDECREF(pvalue); Py_XDECREF(ptype); Py_XDECREF(ptraceback); Py_XDECREF(pvalue_pystr); Py_XDECREF(ptype_pystr); Py_XDECREF(ptraceback_pystr); // Python 3 and up #if PY_VERSION_HEX >= 0x03000000 Py_XDECREF(pvalue_ustr); Py_XDECREF(ptype_ustr); Py_XDECREF(ptraceback_ustr); #endif // PY_VERSION_HEX } else { Py_DECREF(ret); } Py_DECREF(arglist); } PyGILState_Release(gilstate); #else dev->isr(dev->isr_args); #endif #ifdef HAVE_PTHREAD_CANCEL pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); #endif } else { // we must have got an error code or exit request so die nicely #ifdef HAVE_PTHREAD_CANCEL pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); #endif close(dev->isr_value_fp); dev->isr_value_fp = -1; #if defined(SWIGJAVA) || defined(JAVACALLBACK) if(dev->isr == mraa_java_isr_callback) { (*jenv)->DeleteGlobalRef(jenv, (jobject)dev->isr_args); (*globVM)->DetachCurrentThread(globVM); } #endif return NULL; } } }
static void* mraa_gpio_interrupt_handler(void* arg) { mraa_gpio_context dev = (mraa_gpio_context) arg; int fp = -1; mraa_result_t ret; if (IS_FUNC_DEFINED(dev, gpio_interrupt_handler_init_replace)) { if (dev->advance_func->gpio_interrupt_handler_init_replace(dev) != MRAA_SUCCESS) return NULL; } else { // open gpio value with open(3) char bu[MAX_SIZE]; sprintf(bu, SYSFS_CLASS_GPIO "/gpio%d/value", dev->pin); fp = open(bu, O_RDONLY); if (fp < 0) { syslog(LOG_ERR, "gpio%i: interrupt_handler: failed to open 'value' : %s", dev->pin, strerror(errno)); return NULL; } } #ifndef HAVE_PTHREAD_CANCEL if (pipe(dev->isr_control_pipe)) { syslog(LOG_ERR, "gpio%i: interrupt_handler: failed to create isr control pipe: %s", dev->pin, strerror(errno)); close(fp); return NULL; } #endif dev->isr_value_fp = fp; if (lang_func->java_attach_thread != NULL) { if (dev->isr == lang_func->java_isr_callback) { if (lang_func->java_attach_thread() != MRAA_SUCCESS) { close(dev->isr_value_fp); dev->isr_value_fp = -1; return NULL; } } } for (;;) { if (IS_FUNC_DEFINED(dev, gpio_wait_interrupt_replace)) { ret = dev->advance_func->gpio_wait_interrupt_replace(dev); } else { ret = mraa_gpio_wait_interrupt(dev->isr_value_fp #ifndef HAVE_PTHREAD_CANCEL , dev->isr_control_pipe[0] #endif ); } if (ret == MRAA_SUCCESS && !dev->isr_thread_terminating) { #ifdef HAVE_PTHREAD_CANCEL pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); #endif if (lang_func->python_isr != NULL) { lang_func->python_isr(dev->isr, dev->isr_args); } else { dev->isr(dev->isr_args); } #ifdef HAVE_PTHREAD_CANCEL pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); #endif } else { // we must have got an error code or exit request so die nicely #ifdef HAVE_PTHREAD_CANCEL pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); #endif if (fp != -1) { close(dev->isr_value_fp); dev->isr_value_fp = -1; } if (lang_func->java_detach_thread != NULL && lang_func->java_delete_global_ref != NULL) { if (dev->isr == lang_func->java_isr_callback) { lang_func->java_delete_global_ref(dev->isr_args); lang_func->java_detach_thread(); } } return NULL; } } }