Stack level too deep after sem.lock(0)
eugenk opened this issue · 5 comments
Running on redis-semaphore, '0.3.0'
I get "a stack level too deep" after some basic operations:
❯ ruby --version
ruby 2.3.0p0 (2015-12-25 revision 53290) [x86_64-darwin15]
❯ redis-cli flushdb
OK
❯ irb
irb(main):001:0> require 'redis-semaphore'
=> true
irb(main):002:0> l = Redis::Semaphore.new(:abc)
=> #<Redis::Semaphore:0x007fc97316a398 @name=:abc, @expiration=nil, @resource_count=1, @stale_client_timeout=nil, @redis=#<Redis client v3.2.2 for redis://127.0.0.1:6379/0>, @use_local_time=nil, @tokens=[]>
irb(main):003:0> l.lock(0)
=> nil
irb(main):004:0> l.locked?
SystemStackError: stack level too deep
from /usr/local/opt/rbenv/versions/2.3.0/lib/ruby/gems/2.3.0/gems/redis-semaphore-0.3.0/lib/redis/semaphore.rb:98:in `locked?'
from /usr/local/opt/rbenv/versions/2.3.0/lib/ruby/gems/2.3.0/gems/redis-semaphore-0.3.0/lib/redis/semaphore.rb:99:in `block in locked?'
from /usr/local/opt/rbenv/versions/2.3.0/lib/ruby/gems/2.3.0/gems/redis-semaphore-0.3.0/lib/redis/semaphore.rb:98:in `each'
from /usr/local/opt/rbenv/versions/2.3.0/lib/ruby/gems/2.3.0/gems/redis-semaphore-0.3.0/lib/redis/semaphore.rb:98:in `locked?'
from /usr/local/opt/rbenv/versions/2.3.0/lib/ruby/gems/2.3.0/gems/redis-semaphore-0.3.0/lib/redis/semaphore.rb:99:in `block in locked?'
from /usr/local/opt/rbenv/versions/2.3.0/lib/ruby/gems/2.3.0/gems/redis-semaphore-0.3.0/lib/redis/semaphore.rb:98:in `each'
from /usr/local/opt/rbenv/versions/2.3.0/lib/ruby/gems/2.3.0/gems/redis-semaphore-0.3.0/lib/redis/semaphore.rb:98:in `locked?'
from /usr/local/opt/rbenv/versions/2.3.0/lib/ruby/gems/2.3.0/gems/redis-semaphore-0.3.0/lib/redis/semaphore.rb:99:in `block in locked?'
from /usr/local/opt/rbenv/versions/2.3.0/lib/ruby/gems/2.3.0/gems/redis-semaphore-0.3.0/lib/redis/semaphore.rb:98:in `each'
from /usr/local/opt/rbenv/versions/2.3.0/lib/ruby/gems/2.3.0/gems/redis-semaphore-0.3.0/lib/redis/semaphore.rb:98:in `locked?'
from /usr/local/opt/rbenv/versions/2.3.0/lib/ruby/gems/2.3.0/gems/redis-semaphore-0.3.0/lib/redis/semaphore.rb:99:in `block in locked?'
from /usr/local/opt/rbenv/versions/2.3.0/lib/ruby/gems/2.3.0/gems/redis-semaphore-0.3.0/lib/redis/semaphore.rb:98:in `each'
from /usr/local/opt/rbenv/versions/2.3.0/lib/ruby/gems/2.3.0/gems/redis-semaphore-0.3.0/lib/redis/semaphore.rb:98:in `locked?'
from /usr/local/opt/rbenv/versions/2.3.0/lib/ruby/gems/2.3.0/gems/redis-semaphore-0.3.0/lib/redis/semaphore.rb:99:in `block in locked?'
from /usr/local/opt/rbenv/versions/2.3.0/lib/ruby/gems/2.3.0/gems/redis-semaphore-0.3.0/lib/redis/semaphore.rb:98:in `each'
from /usr/local/opt/rbenv/versions/2.3.0/lib/ruby/gems/2.3.0/gems/redis-semaphore-0.3.0/lib/redis/semaphore.rb:98:in `locked?'
... 11515 levels...
from /usr/local/opt/rbenv/versions/2.3.0/lib/ruby/gems/2.3.0/gems/redis-semaphore-0.3.0/lib/redis/semaphore.rb:98:in `each'
from /usr/local/opt/rbenv/versions/2.3.0/lib/ruby/gems/2.3.0/gems/redis-semaphore-0.3.0/lib/redis/semaphore.rb:98:in `locked?'
from /usr/local/opt/rbenv/versions/2.3.0/lib/ruby/gems/2.3.0/gems/redis-semaphore-0.3.0/lib/redis/semaphore.rb:99:in `block in locked?'
from /usr/local/opt/rbenv/versions/2.3.0/lib/ruby/gems/2.3.0/gems/redis-semaphore-0.3.0/lib/redis/semaphore.rb:98:in `each'
from /usr/local/opt/rbenv/versions/2.3.0/lib/ruby/gems/2.3.0/gems/redis-semaphore-0.3.0/lib/redis/semaphore.rb:98:in `locked?'
from /usr/local/opt/rbenv/versions/2.3.0/lib/ruby/gems/2.3.0/gems/redis-semaphore-0.3.0/lib/redis/semaphore.rb:99:in `block in locked?'
from /usr/local/opt/rbenv/versions/2.3.0/lib/ruby/gems/2.3.0/gems/redis-semaphore-0.3.0/lib/redis/semaphore.rb:98:in `each'
from /usr/local/opt/rbenv/versions/2.3.0/lib/ruby/gems/2.3.0/gems/redis-semaphore-0.3.0/lib/redis/semaphore.rb:98:in `locked?'
from /usr/local/opt/rbenv/versions/2.3.0/lib/ruby/gems/2.3.0/gems/redis-semaphore-0.3.0/lib/redis/semaphore.rb:99:in `block in locked?'
from /usr/local/opt/rbenv/versions/2.3.0/lib/ruby/gems/2.3.0/gems/redis-semaphore-0.3.0/lib/redis/semaphore.rb:98:in `each'
from /usr/local/opt/rbenv/versions/2.3.0/lib/ruby/gems/2.3.0/gems/redis-semaphore-0.3.0/lib/redis/semaphore.rb:98:in `locked?'
from /usr/local/opt/rbenv/versions/2.3.0/lib/ruby/gems/2.3.0/gems/redis-semaphore-0.3.0/lib/redis/semaphore.rb:99:in `block in locked?'
from /usr/local/opt/rbenv/versions/2.3.0/lib/ruby/gems/2.3.0/gems/redis-semaphore-0.3.0/lib/redis/semaphore.rb:98:in `each'
from /usr/local/opt/rbenv/versions/2.3.0/lib/ruby/gems/2.3.0/gems/redis-semaphore-0.3.0/lib/redis/semaphore.rb:98:in `locked?'
from (irb):4
from /usr/local/opt/rbenv/versions/2.3.0/bin/irb:11:in `<main>'irb(main):005:0>
I did some debugging:
In line 73, nil
is added to the array @tokens
. This causes locked?
to recurse indefinitely.
This is because for timeout == 0
, we go into the "else" part in line 67 and lpop
does not return an array, but only a string ("0"
).
Then, current_token = token_pair[1]
line 72 is not the string that it should be. It is rather nil
.
I'm not sure what the expected/intended behaviour is, so I won't create a pull request. I hope this debugging helps you fix the problem.
👍
I face the same issue. This bug makes lock(0)
not work at all (it always returns nil).
Any chance this is going to get merged/fixed in a new version soon? I ran into this issue as well... my particular use needs it to return immediately if the semaphore cannot be locked. Another workaround would be to allow fractions of a second... but that does not appear to work either :)
Interesting! I'll try to have a look soon and fix this. My apologies for the delay on this, and thanks for putting in the time and debugging the issue!