pi_piper
pi_piper copied to clipboard
Trouble with Device or resource busy
Hi I am unable to get the pins to work on the latest version of noobs.
Running
File.open("/sys/class/gpio/export", "w") { |f| f.write("7") }
Error
Errno::EBUSY: Device or resource busy @ fptr_finalize - /sys/class/gpio/export
Using: https://github.com/robert2d/raspberry-pi-gpio-rails4-control
I have manually run the command via a rails console using rvmsudo bundle exec rails c
. I have checked forums and other resources on google and cannot find a solution, so I was hoping somebody could point me(slash my pins :smile:) in the right direction.
Also:
Running echo 7 >/sys/class/gpio/unexport
seems to free up the pin again but re running the above twice causes the same error again.. (reference: http://squarism.com/2014/09/24/redis-595-timer-states/)
Thanks
Out of curiosity are you running into this problem when you are running the application on the pi or on your desktop / non-pi?
lol on the Pi of course. I have investigated some more and found that I can get a pin and manipulate it when its stored in the rails console. But as soon as I flush the variable or try to get a new pin I run into the error above.
I had this same issue. Seems like the only solution is to manually release each pin when you're done using it (echo GPIO_NUM > /sys/class/gpio/unexport
). I've had no issues since I started doing that.
Clearly pi_piper
does not clean up after itself, as it should.
I use this workaround:
pins.each do |pin|
File.open("/sys/class/gpio/unexport", "w") { |f| f.write("#{pin}") }
end
but it obviously should be fixed in the gem.
https://github.com/jwhitehorn/pi_piper/pull/31 This should fix. What do you guys think?
@github0013 Looks good, but wouldn't it be better if Pin.release
was private? I don't know if you should be able to manually release a pin that's allocated to a Pin
object. You could get into trouble holding onto a Pin
that's been released like that, I imagine.
If its private you cannot reliably release a pin. If you loose reference to a pin object you have this pin locked until GC removes the object. Am i right?
Yeah, but there shouldn't be any reason to release a pin that's sensitive to how quickly the GC releases it. Or should there? Maybe I'm just nitpicking.
Nevermind, you're right. There could be multiple programs trading off using the pins or something similar. Carry on, ignore me. :stuck_out_tongue:
I think there aren't many cases you would use a pin for IN and OUT as your program go. So basically, you won't manually have to release any pins although it is a public method.
Once you set up a pin, you would use it as it is until the program ends. And normally you will be holding the pin object until your program ends (otherwise you can't control the pin). Since you hold on to it, GC
won't run the unexport
finalizer proc to release unexpectedly.
finalizer
will at least release pins used at exit so that the next time you run any programs using the same pin, won't raise the busy
exception.
If you have to have a pin IN then later OUT in a program, you can release it by PiPiper::Pin.release(pin_number)
and switch it to IN or OUT.
I agree. Have only one doubt. Are you sure, that the finalizer will always be called? As I remember, in Java descructor was called only if an object was destroyed by GC, but not when it was destroyed when virtual machine was being shut down. Consequently, it might happen that descrutcor was never called and it was documented. Ruby docs say nothing about it. That leaves my with doubts rather then certainty.
I wrote a test to check this. Seems to consistently clean everything up before exiting the program, but I don't know if anything could affect that.
Hard to tell, if doc says nothing...
JA http://docs.ruby-lang.org/ja/1.9.3/method/ObjectSpace/m/define_finalizer.html EN http://ruby-doc.org/core-1.9.3/ObjectSpace.html#method-c-define_finalizer
EN doc doesn't really say much about define_finalizer
whereas JA has more.
translated:
https://translate.google.co.jp/translate?sl=ja&tl=en&js=y&prev=_t&hl=ja&ie=UTF-8&u=http%3A%2F%2Fdocs.ruby-lang.org%2Fja%2F1.9.3%2Fmethod%2FObjectSpace%2Fm%2Fdefine_finalizer.html&edit-text=&act=url
JA doc talks about exiting or raising exceptions in the finalizer proc. It says they will be ignored. proc の呼び出しで発生した大域脱出(exitや例外)は無視されます。 my translation: global escapes (ex: exit or exceptions) that are called within this proc will be ignored
if you ask me "Are you sure, that the finalizer will always be called?", then I can interpret this as "since all finalizers will be called at least at the exit, bad things(exiting on the main exit or raising errors) need to be ignored."
https://github.com/jwhitehorn/pi_piper/pull/32
I found at_exit
in platform.rb.
If you use Gemfile to require this branch by bundle install --path vendor/bundle
, and you cron a job, make sure that you add bundle exec ruby ...
in your command.
ex:
yoru_ruby_file.rb
require 'bundler/setup'
require "pi_piper"
...
...
crontab
* * * * * /bin/bash -l -c 'cd /full/path/to/; bundle exec ruby /full/path/to/yoru_ruby_file.rb'
EN doc doesn't really say much about define_finalizer whereas JA has more. translated:
So far for English as discussion language about Ruby...
Thanks for finding this page. It doesn't ensure that finalizer will be called, but giving tempfile
as example using it reliably is quite convincing for me. Certainly sufficient for the case of pi_piper pins.
How can I make this to work using RVM?, everytime I load a ruby script with pi_piper says: bcm2835_init: Unable to open /dev/mem: Permission denied
run as root... I know it is lame but bcm2835 won't work without root privileges... and worse -- /sys
interface to GPIO does not require root privileges, but bcm2835 is wiser and so it requires root... lame...
@joecabezas Try using rvmsudo
i.e. rvmsudo ruby ./my_script.rb
Should be solved with V1.9.9 update the gem and see. If everything is ok please close the issue
@wrzasa should your code be this? I'm not trying to be an ass, I'm just trying to make sure I'm thinking correctly:
pins.each do |pin| # changed led to pin
File.open("/sys/class/gpio/unexport", "w") { |f| f.write("#{pin}") }
end
I've just started w/this gem and running a very simple example (which may be poorly written, by me) and I'm getting this error (among others) and googling brought me here. FWIW I am using v1.9.9 on a RPi, broadcom obviously, ruby v2.1.5p273 (2014-11-13)
@kernelsmith, Still have this issue with 1.9.9 !? It would b possible if you used gpio outside PiPiper after the last boot.
try to reboot and test.
@kernelsmith Yes, you are correct: led in my code should be changed to pin. Just corrected this in my previous comment. Thanks!
@wrzasa I'm still getting the error, haven't looked into it much, but as an example: https://gist.github.com/kernelsmith/c7beb8377e558cdb8f12
This is on a fresh install and having done nothing else to the gpio pins whatsoever
@kernelsmith There is something strange about the code you show. I don't know why the first usage of pin 22 ends up with the resource busy error if you didn't use the pin after last reboot. The second error is more strange because it shows incorrect path to export
file. I don't have Pi running now, but AFAIR instead of: /sys/class/gpio/gpio/direction
it should be /sys/class/gpio/direction
. But it would not work anyway, because of the way pi_piper is designed: you cannot do more then once watch
or after
on a single pin... (yes it sucks!). If you want to react on different changes on a single pin you must put it all in a single watch
/after
/before
block. And you cannot create Pin
object for a pin you did a watch
or after
or you will get the 'resource busy' error. Thus the last error on watch
would happen anyway if any of the previous usages of the pin succeeded.
Maybe you mixed Pin.new
and watch
/after
calls on a single pin and that's why you get the resource busy error?
You can always monitor files in /sys/class/gpio
and check when directories for pins appear. If a pin is already exported (directory for this pin is created in /sys/class/gpio
) you will get 'resource busy' error trying to watch
or Pin.new
on this pin.
@kernelsmith I just took a very quick glance at this.
I found out why /sys/class/gpio/gpio/direction
is happening. It should be /sys/class/gpio/gpioPinNumber/direction
but something is not setting PinNumber which is why the path look incorrect.
The other part is when calling after
or watch
, a pin
object is automatically allocated. Did you already open pin 22?
I will look into this a bit more myself. I think maybe we can attempt to allow watch
to be run multiple times.
@kernelsmith Figured out why we have gpio/gpio/direction
, you have a typo here: https://gist.github.com/kernelsmith/c7beb8377e558cdb8f12#file-pi_piper_error-L26
It should be pin: 22
not in: 22
:smile:
That's why people found out data validation... Not funny at all, Pin
class should validate this in constructor and maybe watch
should also do it...
Thanks. Apologies, I'm overseas for a few days so I won't have any meaningful responses/feedback for a week or so
On Feb 20, 2016, at 11:34, Zshawn Syed [email protected] wrote:
@kernelsmith Figured out why we have gpio/gpio/direction, you have a typo here: https://gist.github.com/kernelsmith/c7beb8377e558cdb8f12#file-pi_piper_error-L26
It should be pin: 22 not in: 22
— Reply to this email directly or view it on GitHub.
Alright I just tried this on my actual pi and was not able to reproduce your error. However I am using ruby 2.2.1
. I know that isn't helpful but I am hoping to at least reproduce this bug somehow.
This is exactly what I tried:
$ rvmsudo irb
require 'pi_piper' # => 1.9.9
include PiPiper
pin4 = PiPiper::Pin.new(:pin => 4, :direction => :out)
#<PiPiper::Pin:0x18b58d8 @pin=4, @direction=:out, @invert=false, @trigger=:both, @pull=:off, @released=false, @last_value=nil, @value=0>
pin4.value
# => 0
pin4.on
# => 1
pin4.off
# => 1
after :pin => 22, :goes => :high do
puts "pin 22 just went high"
end
#<Thread:0x5808c0@/home/pi/.rvm/gems/ruby-2.2.1/gems/pi_piper-1.9.9/lib/pi_piper.rb:14 sleep>