GPIO.setup() error only when app started with crontab. not with Thonny or terminal

I am converting a large python3 with Flask program written for RPi (controlling our chicken coop doors and water heaters etc). It is working great when prog is activated via Thonny or from terminal via python3 <directory/progname.py>
But, when I put the prog into crontab -e (not sudo) it gives an error: ’

gpio.setup(“P8_26”, gpio.OUT)
ValueError: Set gpio direction failed, missing file or invalid permissions’

In crontab, it is listed as: "@reboot python3 directory/gpio_trial.py

I wrote a little trial program to play with this issue, and it does the same: works from terminal/ Thonny, not when included in crontab -

import Adafruit_BBIO.GPIO as gpio
import time
gpio.setup("P8_26", gpio.OUT)
while True:
    gpio.output("P8_26", gpio.HIGH)
    time.sleep(0.5)
    gpio.output("P8_26", gpio.LOW)
    time.sleep(0.5)

Apology, I don’t know the markdown symbols to use to put the code into a code-window / block

Why are you using crontab to run a flask app ?
Are you doing this just to get it to auto run when powering up ?

Not sure how the Adafuit library is accessing the GPIO but the error message is quite a good clue.
As you can run it normally in a terminal, it probably isn’t a permissions error, assuming the cron job is running as you.

That would just leave missing file error. It is possible that your app is running before the GPIO is visible, maybe down to udev.

I think also I have seen a udev rule that sets the permissions on some of the I/O files, which may include GPIO. If this is running after your program then the permissions won’t be set by the time your software tries to access the GPIO.

You could probably test this by putting a long sleep at the start of your program and see if that works.

TY for reply!
I do run a flask portion of the main program over a browser, of course.
But, the main also has portions to be accessed over LAN only, not involving Flask.
So, crontab loads the Main App.
I do not know what udef is, but will research. I will try the pause at the start of the program to see what it will do - TY for suggestion!
Oh, interestingly though: The error comes a few lines AFTER Adafruit_BBB_GPIO library is imported as PGIO. I am not sure if that means anything

importing the library probably doesn’t do anything at import time.

udev is the plug and play stuff, often associated with USB, but it gets triggered for all sorts of things.

most of the rules are in /etc/udev/rules.d

for example on my BBB which is a Debian buster image from 2020 so not exactly new there is a udev rule ( 80-gpio-noroot.rules ) that sets the group and permissions for the sys gpio files.

Assuming it is the same on your BBB this is probably the cause of your problems.

I sudo nano’ed /etc/udev/rules.d and it returned an empty screen.

That’s a directory

Got it!
This is what shows in 800gpio-noroots.rules:
SUBSYSTEM==“gpio”, ACTION==“add”,
RUN+=“/bin/chgrp -R gpio ‘/sys%p’”,
RUN+=“/bin/chmod -R g=u ‘/sys%p’”

SUBSYSTEM==“subsystem”, KERNEL==“gpio”, ACTION==“add”,
RUN+=“/bin/chgrp gpio ‘/sys/class/gpio/export’ ‘/sys/class/gpio/unexport’”,
RUN+=“/bin/chmod g=u ‘/sys/class/gpio/export’ ‘/sys/class/gpio/unexport’”

and this shows in 85-gpio-noroot.rules:
KERNEL==“gpiochip*”, SUBSYSTEM==“gpio”, MODE=“0660”, GROUP=“gpio”

I have, on BBB initial setup, added me (new user) into the gpio group

Ok so assuming you set your cron job to run at boot, it is more than likely running before the udev rules change ownership and so your program fails.

You need to modify your source to be more robust.
You could just stick a sleep at the start to delay your software but that is a bad way to do it.

Put a try catch around your gpio setup. If it fails, sleep for a bit and try again. Repeat a few times and if it still fails print out an error and quit.

How long do you sleep and how many retries ?

Well that’s impossible to predict precisely. I would sleep for at least 2 seconds maybe 5, and then repeat for at least 30 seconds before giving up and quitting.

If you use systemd rather tahn cron to start your program, then if it quits unexpectedly, systemd will at least restart it. Thats assuming your BBB is using systemd.

OK, I tried several different ways but held the line execution of gpio.setup() for 1 minute max. Still didn’t work.
Then, I added the same trial program to crontab without the @reboot, setting it to start every 5 minutes (just so it would start) and it worked perfectly.
So, it must have something to do with the @reboot?

Based on benedict.hewson suggestion (and being correct in a solution work-around), I did some experimenting with Try and While conditions. None really worked to get get the problem solved.
But, the idea of a sleep condition was spot on.
I did some research into cron, and found it has it’s own sleep function, example:
< @reboot sleep 60 ; python3 <program path/program name>
works like a charm.
I am surprised this issue has not come up before? Aren’t many people using RPi’s and BB’s using GPIO’s and many using cron to start these programs?
Anyway, TY benedict.hewson and hopefully this will help others as well.

1 Like

it interesting that delaying cron job works but not delaying within the program.

if I get time I will have to play around with it and see what the root cause is.

I would say most people would create a systemd service to start something, or you can use systemd timers if you need something to run periodically.
Or even good old SYSV init scripts.

I am also continuing research on this, but little found online. I would imagine it is BB specific, since it is the same program which works flawless across all my RPi’s from Pi Zero W to 4B+
TY for continuing to work on it!
I now have a successful conversion of my code - not as involved as I thought, using a config file for variables so I can switch from RPi to BBB with config.py rather than having to make the changes in the program itself.
TY for saving me - I was going to give up.
Rainer