3

I have a Java program that is using pi4j project to interact with the GPIOs. I have one test class that listens for a button to be pressed and then does something. The class is part of many in a larger program and it is possible that it is created and run multiple times, and this is causing the problem.

On the first execution I have no problem and everything runs and works as expected, but when executing a second (or more) times then I'm getting an "RejectedExecutionException" error when the button is pressed.

Full stack trace

Exception in thread "Thread-14" java.util.concurrent.RejectedExecutionException: Task com.pi4j.io.gpio.tasks.impl.GpioEventDispatchTaskImpl@11f409d rejected from java.util.concurrent.ThreadPoolExecutor@1d8bcce[Terminated, pool size = 0, active threads = 0, queued tasks = 0, completed tasks = 12]
at java.util.concurrent.ThreadPoolExecutor$AbortPolicy.rejectedExecution(ThreadPoolExecutor.java:2047)
at java.util.concurrent.ThreadPoolExecutor.reject(ThreadPoolExecutor.java:823)
at java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:1369)
at com.pi4j.concurrent.ShutdownDisabledExecutorWrapper.execute(ShutdownDisabledExecutorWrapper.java:113)
at com.pi4j.io.gpio.impl.GpioEventMonitorExecutorImpl.handlePinEvent(GpioEventMonitorExecutorImpl.java:91)
at com.pi4j.io.gpio.GpioProviderBase.dispatchPinDigitalStateChangeEvent(GpioProviderBase.java:332)
at com.pi4j.io.gpio.RaspiGpioProvider.pinStateChange(RaspiGpioProvider.java:206)
at com.pi4j.wiringpi.GpioInterrupt.pinStateChangeCallback(GpioInterrupt.java:126)

Now to me it seems like something is not being shutdown properly, but I can't find what it is!

My code is as follows;

Constructor

GpioPinDigitalInput buttonPin;


this.buttonPin = gpio.provisionDigitalInputPin(RaspiPin.GPIO_03, PinPullResistance.PULL_DOWN);      
this.buttonPin.setShutdownOptions(true, PinState.LOW);  
this.buttonPin.addListener(this);

Shutdown

this.buttonPin.removeAllListeners();
gpio.unprovisionPin(buttonPin);
this.gpio.shutdown();

I would appreciate some help to track down what the problem is.

Thanks

  • any luck fixing this up? facing the same issue – mikebertiean Jul 5 '16 at 19:16
  • No luck, and to be honest I gave up as I was just messing around! – jason.kaisersmith Jul 7 '16 at 9:52
  • 1
    Did you try the suggestion from your Pi4J bug report, i.e. not shutting down the GPIOs before the application's final termination? – goobering Jul 8 '16 at 9:08
  • Thanks to @goobering I was able to resolve this issue by removing the gpio.shutdown() line. Thanks! – mikebertiean Jul 11 '16 at 16:05
3
+50

Per the comments below the question, I can't really take the credit for this. jason.keisersmith had received a reply to a bug report posted to the Pi4J Github page here by user savageautomate on 18/03/16, which suggested:

If the entire program/process is not terminating, then you probably should not use the this.gpio.shutdown(); call. You should be able to provision and un-provision pins just fine as often as needed in a process. this.gpio.shutdown(); is really for when you are completely terminating your application/process. It will do things like un-export the GPIO pin and set it to a default shutdown state.

Again, per the comments below the question, the solution was to remove the gpio.shutdown line from the code.

0

The above mentioned answer is correct. I'm sharing you sample code, for more clarity with code which I used to overcome this issue. Solution to the point: From gpio we are provisioning Digital Output Pin and after any specific task like on, off, toggle or blink. If you unprovisionPin then the status of pin as before. What we are doing here is provisioning Pin 1 and perform toggle operation. Once toggle operation is completed. We are unprovisioning Pin.

gpioPinDigitalOutput =  gpio.provisionDigitalOutputPin(RaspiPin.GPIO_01, "Led1" , PinState.LOW);
gpioPinDigitalOutput.toggle();
gpio.unprovisionPin(gpioPinDigitalOutput);

Some more code for your reference that is useful: Below is your controller. Mostly, this issue occur in blink and pulse.

@RestController
public class LedController {
private static final GpioController gpio = GpioFactory.getInstance();
private GpioPinDigitalOutput gpioPinDigitalOutput;

@RequestMapping("/{colour}/blink")
public String blink(@PathVariable("colour") String colour) {
    gpioPinDigitalOutput= gpio.provisionDigitalOutputPin(CommonUtils.getPinNumber(colour), colour, PinState.LOW);
    gpioPinDigitalOutput.blink(200L, 5000L);
    gpio.unprovisionPin(gpioPinDigitalOutput);
    return "Light is blinking...";
    }
}

My Utility Class: You can map to Enum but I'm using simple approach for an example:

public class CommonUtils {

public static Pin getPinNumber(String colour) {
    Pin pin = null;
    if(colour.equals("red")) {
        pin= RaspiPin.GPIO_01;
    }
    else if(colour.equals("yellow")) {
        pin= RaspiPin.GPIO_02;
    }
    else if(colour.equals("green")) {
        pin= RaspiPin.GPIO_03;
    }
    return pin;
    }
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.