`@_shield` memoization doesn't remove authenticated state for user
christiankakesa opened this issue · comments
I use Shield in rack application with Syro. On logout, I suspect that @_shield
memoization persist the authenticate state of user.
For now I remove @_shield
memoization and it works :
https://github.com/fenicks/forgedtofight.io/blob/master/decks/basic_deck.rb#L9.
Is it safe to do so ?
I'm suspecting @_shield
is not thread safe. I I'll try something later today, because looking at the code @_shield[model]
is eliminated on logout, but it could be the case that it is deleted only in one thread. Or maybe I'm talking nonsense, I'll investigate and let you know. Which webserver are you using?
Good point, I'm using Unicorn (Worker/Multi processes/single thread).
When I try with Webrick it works perfectly.
Can you try this?
module Shield
private
class ThreadSafeHash
def initialize
@hs = Hash.new
end
def hs
@hs[Thread.current.object_id] ||= Hash.new
end
def [](key)
hs[key]
end
def []=(key, value)
hs[key] = value
end
def delete(key)
hs.delete(key)
end
end
end
Then, in authenticated
:
def authenticated(model)
@_shield ||= ThreadSafeHash.new
@_shield[model] ||= session[model.to_s] && model[session[model.to_s]]
end
I tryed, but it doesn't fix the problem on logout with Unicorn, works with WEBrick.
It's probably because of workers.
Unicorn launch at least 2 worker and the strategy is round robin (I guess).
It could work with sticky mechanism on workers but it's too heavy.
In this situation we probably need a shared data structure between workers which Rack::Session::NoBrainer is (in my case) but It's a slow solution that serialize @_shield
in session.
Don't know if there is a good solution for that ?