Have wiringPiISR and wiringPiISR2 return error on failure in initialization
The each function initializes the event listener loop in a spawned listener thread. The new thread does not report errors back to the original caller. So the function misses initialization errors. The code is fixed to initialize the event listener in the original thread before spawning the listener thread so that the function can pick up errors and return them to the user.
This commit is contained in:
@@ -2868,30 +2868,24 @@ int waitForInterruptClose(int pin) {
|
||||
}
|
||||
|
||||
/*
|
||||
* interruptHandlerV2:
|
||||
* This is a thread and gets started to wait for the interrupt we're
|
||||
* hoping to catch. It will call the user-function when the interrupt
|
||||
* fires.
|
||||
* interruptHandlerInit:
|
||||
* Initializes an interrupt handler before starting the listener loop in a
|
||||
* separate thread.
|
||||
* Returns: >0 on successful initialization, 0 if the listener loop does not
|
||||
* have to start, -1 on error.
|
||||
*********************************************************************************
|
||||
*/
|
||||
|
||||
void *interruptHandlerV2(void *arg)
|
||||
static int interruptHandlerInit(int pin)
|
||||
{
|
||||
const char* strmode = "";
|
||||
int pin, EdgeMode, ret, fd, attr, i;
|
||||
unsigned int readret;
|
||||
int EdgeMode, ret, attr;
|
||||
unsigned long debounce_period_us;
|
||||
struct pollfd polls ;
|
||||
struct gpio_v2_line_config config;
|
||||
struct gpio_v2_line_request req;
|
||||
struct gpio_v2_line_event evdat[64];
|
||||
struct WPIWfiStatus wfiStatus;
|
||||
struct timespec tspec = {0, 5e5}; /* 0.5 ms timeout {0, 1e6} */
|
||||
|
||||
pin = *(int *)arg;
|
||||
|
||||
if (wiringPiGpioDeviceGetFd() < 0) {
|
||||
return NULL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
EdgeMode = isrEdgeMode[pin];
|
||||
@@ -2912,7 +2906,7 @@ void *interruptHandlerV2(void *arg)
|
||||
if (wiringPiDebug) {
|
||||
printf ("interruptHandlerV2: waitForInterruptMode edge mode INT_EDGE_SETUP - exiting\n") ;
|
||||
}
|
||||
return NULL;
|
||||
return 0;
|
||||
case INT_EDGE_FALLING:
|
||||
config.flags |= GPIO_V2_LINE_FLAG_EDGE_FALLING;
|
||||
strmode = "falling";
|
||||
@@ -2944,14 +2938,44 @@ void *interruptHandlerV2(void *arg)
|
||||
ret = ioctl(chipFd, GPIO_V2_GET_LINE_IOCTL, &req);
|
||||
if (ret == -1) {
|
||||
ReportDeviceError("interruptHandlerV2: get line event", pin , strmode, ret);
|
||||
return NULL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (wiringPiDebug)
|
||||
if (wiringPiDebug) {
|
||||
printf ("interruptHandlerV2: GPIO get line %d , mode %s succeded, fd=%d\n", pin, strmode, req.fd);
|
||||
}
|
||||
|
||||
return req.fd;
|
||||
}
|
||||
|
||||
struct interrupt_handler_params {
|
||||
int pin;
|
||||
int fd;
|
||||
};
|
||||
|
||||
/*
|
||||
* interruptHandlerV2:
|
||||
* This is a thread and gets started to wait for the interrupt we're
|
||||
* hoping to catch. It will call the user-function when the interrupt
|
||||
* fires.
|
||||
*********************************************************************************
|
||||
*/
|
||||
|
||||
static void *interruptHandlerV2(void *arg)
|
||||
{
|
||||
struct interrupt_handler_params *params;
|
||||
int pin, ret, fd, i;
|
||||
unsigned int readret;
|
||||
struct pollfd polls ;
|
||||
struct gpio_v2_line_event evdat[64];
|
||||
struct WPIWfiStatus wfiStatus;
|
||||
struct timespec tspec = {0, 5e5}; /* 0.5 ms timeout {0, 1e6} */
|
||||
|
||||
params = (struct interrupt_handler_params *)arg;
|
||||
pin = params->pin;
|
||||
fd = params->fd;
|
||||
|
||||
/* set event fd */
|
||||
fd = req.fd;
|
||||
isrFds [pin] = fd;
|
||||
|
||||
(void)piHiPri (55) ; // Only effective if we run as root
|
||||
@@ -3041,9 +3065,8 @@ void *interruptHandlerV2(void *arg)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* wiringPiISR:
|
||||
* wiringPiISRInternal:
|
||||
* Pi Specific.
|
||||
* Take the details and create an interrupt handler that will do a call-
|
||||
* back to the user supplied function.
|
||||
@@ -3077,26 +3100,35 @@ int wiringPiISRInternal(int pin, int edgeMode, void (*function)(struct WPIWfiSta
|
||||
printf("wiringPi: mutex in\n");
|
||||
}
|
||||
pthread_mutex_lock (&pinMutex) ;
|
||||
struct interrupt_handler_params params = {
|
||||
.pin = pin,
|
||||
};
|
||||
params.fd = interruptHandlerInit(pin);
|
||||
if (params.fd < 0) {
|
||||
pthread_mutex_unlock (&pinMutex) ;
|
||||
return -1;
|
||||
}
|
||||
|
||||
pinPass = pin ;
|
||||
if (params.fd > 0) {
|
||||
if (wiringPiDebug) {
|
||||
printf("wiringPi: pthread_create before 0x%lX\n", (unsigned long)isrThreads[pin]);
|
||||
}
|
||||
if (pthread_create (&isrThreads[pin], NULL, interruptHandlerV2, &pin)==0) {
|
||||
if (pthread_create (&isrThreads[pin], NULL, interruptHandlerV2, ¶ms)==0) {
|
||||
if (wiringPiDebug) {
|
||||
printf("wiringPi: pthread_create successed, 0x%lX\n", (unsigned long)isrThreads[pin]);
|
||||
}
|
||||
/* while (pinPass != -1)
|
||||
delay (1) ; */
|
||||
// wait so that interruptHandler is up und running.
|
||||
// when interruptHandler is running, the calling function wiringPiISR
|
||||
// must be still alive, otherwise the thread argument &pin points into nirwana,
|
||||
// when it is picked up from interruptHandler.
|
||||
delay (10);
|
||||
} else {
|
||||
if (wiringPiDebug) {
|
||||
printf("wiringPi: pthread_create failed\n");
|
||||
}
|
||||
}
|
||||
// wait so that interruptHandler is up und running.
|
||||
// when interruptHandler is running, the calling function wiringPiISRInternal
|
||||
// must be still alive, otherwise the thread argument ¶m points into nirwana,
|
||||
// when it is picked up from interruptHandlerV2.
|
||||
delay(10);
|
||||
}
|
||||
|
||||
if (wiringPiDebug) {
|
||||
printf("wiringPi: mutex out\n");
|
||||
|
||||
Reference in New Issue
Block a user