Closed pelargir closed 11 years ago
better_errors only keeps the most recent exception around for the sake of preventing memory leaks. If you have another exception occur after the one you're currently investigating, it'll tell you that your session has expired.
I'm 99% sure that only one exception is being thrown in this situation. I can inspect the values of "primitive" vars just fine (integers, strings, etc) but when I try to inspect objects in the local scope, I get "Session expired."
I have a theory on what might be causing this, I'll try to fix it tonight
On Thursday, 13 December 2012 at 1:03 PM, Matthew Bass wrote:
I'm 99% sure that only one exception is being thrown in this situation. I can inspect the values of "primitive" vars just fine (integers, strings, etc) but when I try to inspect objects in the local scope, I get "Session expired."
— Reply to this email directly or view it on GitHub (https://github.com/charliesome/better_errors/issues/40#issuecomment-11319173).
:+1: for some fix. I have the same issue here on our application. Even inspecting local variables leads to variable-but-swift session expiration. No other exception is raised in the mean time.
Cool gem, still !
+1
+1. I can print params
once, but on subsequent attempts, I get Session expired
.
>> p params
=> {"action"=>"dashboard", "controller"=>"accounts"}
>> p params
Session expired
>> undefined
From a pretty stock exception I caused:
def dashboard
current_user.name = bar
end
undefined local variable or method `bar' for #<AccountsController:0x00000006fdd328>
I believe this is caused by unicorn. I'm guessing it's to do with having multiple workers but haven't dug into the code at all. I don't get the same error if I use Thin.
@nfm Multiple workers certainly will cause an issue. Better Errors works by keeping the error state around in memory. If you send a REPL or local variable request back, that will need to run on the same worker the error happened on.
Wow, thanks for the quick response. Awesome gem btw :)
Can others in this thread comment on whether they're using multiple workers for their server?
I'm definitely using multiple workers on my development box. Unicorns, even...
The only very dirty workaround I see would be to store the worker pid in the error state and the retry the command until the correct worker answers. How awful :(
Pierre Baillet (en vadrouille)
Le dimanche 16 décembre 2012 à 05:14, Nicholas Firth-McCoy a écrit :
Wow, thanks for the quick response. Awesome gem btw :) Can others in this thread comment on whether they're using multiple workers for their server?
— Reply to this email directly or view it on GitHub (https://github.com/charliesome/better_errors/issues/40#issuecomment-11414080).
I don't intend to support multiple development workers, simply because it adds a huge amount of extra complexity and it isn't a very common use case
Yes, I am using multiple workers via Unicorn. So that would explain the behavior.
Cool, good to know that was the cause.
This is exactly what I was looking for.
I'm using Pow and by default it spawns 3 workers, so I had to add to my ~/.powconfig
the following line export POW_WORKERS=1
It's not uncommon for a request to your app to need another request to your app to succeed. In my case I have a parallel process that depends on some assets to be served by unicorn while http request is waiting. Having only 1 worker turns this into a deadlock. Perhaps the complexity of supporting >1 worker could, after all, be worth it?
There is a significant amount of complexity in supporting multiple workers. Better Errors relies on leaving a bunch of data in memory in the process where the exception was thrown (eg. the binding stack).
It's not possible to migrate these objects between processes, so the only way to support multiple workers is to have workers connect to other workers. If you go down this path, then you also have to worry about how workers 'discover' which worker they should connect to when they need to use the binding objects.
I don't think supporting an uncommon use case like this is worth all the extra complexity.
For what it's worth maybe there is a simpler approach: teach unicorn/pow to use a worker pid supplied in a request header. Every app response would have worker pid injected via simple middleware. Every eval request would then supply it in the header. Unicorn extension would send it to the correct worker. I know it's still complex, but perhaps not as complex as IPC.
I think @maxim solution is indeed the most elegant as it also removes the IPC complexity from @charliesome excellent Betters Errors. However, adding that kind of feature to unicorn is going to be a bit of hardcore negotiation with the maintainer of the project, Eric Wong, which is a very good but hard to convince product manager...
I certainly didn't mean that we should change unicorn. Merely extend it with another gem, something like better_errors-unicorn.
On Fri, Mar 15, 2013 at 4:52, Pierre Baillet notifications@github.com="mailto:notifications@github.com"> wrote: I think @maxim solution is indeed the most elegant as it also removes the IPC complexity from @charliesome excellent Betters Errors. However, adding that kind of feature to unicorn is going to be a bit of hardcore negotiation with the maintainer of the project, Eric Wong, which is a very good but hard to convince product manager...
— Reply to this email directly or view it on GitHub.
On Fri, Mar 15, 2013 at 4:52 AM, Pierre Baillet notifications@github.com wrote:
I think @maxim solution is indeed the most elegant as it also removes the IPC complexity from @charliesome excellent Betters Errors. However, adding that kind of feature to unicorn is going to be a bit of hardcore negotiation with the maintainer of the project, Eric Wong, which is a very good but hard to convince product manager...
Reply to this email directly or view it on GitHub: https://github.com/charliesome/better_errors/issues/40#issuecomment-14949852
I'm running into the same problem as @maxim, fwiw. I have to have multiple workers for my app, and so better_errors's repl isn't working for me.
The README addition in 2c5d3bc48bfb82f5ba6114572f20f87f7425e9f3 is great, though I didn't check there first – maybe tweaking the error message could be even more helpful? Happy to contribute a pull request if @charliesome agrees. Perhaps "Session expired (Using a multi-worker server? See README.)"
Oh, and if you use Unicorn and temporarily want to decrease the number of workers:
ps aux | grep unicorn
# let's assume master has pid 12345
kill -SIGTTOU 12345 # remove one worker
I've used @henrik's solution and tried running it with Webrick as well and I've come to no avail :/
I am getting this problem with Thin. Is Thin also multi threaded by default?
I managed to fix this in unicorn by forcing the number of worker processes to be 1. better_errors
is so much better now!
Guys, I am using Unicorn and in my dev I have set it to only one worker, but still when I raise an exception in my view I get "session expired"?!
if ENV['RAILS_ENV']=="development"
worker_processes Integer 1
timeout 5000
else
worker_processes Integer(ENV["WEB_CONCURRENCY"] || 2)
timeout 15
end
Have you verified that it only starts one worker (e.g. with "ps ax | grep unicorn")? I'm not sure whether RAILS_ENV is set at that point.
On Sat, Nov 1, 2014 at 2:38 PM, Luka notifications@github.com wrote:
Guys, I am using Unicorn and in my dev I have set it to only one worker, but still when I raise an exception in my view I get "session expired"?!
if ENV['RAILS_ENV']=="development" worker_processes Integer 1 timeout 5000 else worker_processes Integer(ENV["WEB_CONCURRENCY"] || 2) timeout 15 end
— Reply to this email directly or view it on GitHub https://github.com/charliesome/better_errors/issues/40#issuecomment-61368436 .
Hi Henrik,
Yes, it starts only one worker, but there are two processes worker and a master...
41037 0,0 3,1 2836428 260424 s002 S+ ... 1:23.63 unicorn worker[0] -p 5000 -c ./config/unicorn.rb
41030 0,0 1,5 2641736 128944 s002 S+ ... 0:06.96 unicorn master -p 5000 -c ./config/unicorn.rb
thanks
I'm trying to use the REPL from an exception raised inside a presenter object, but when I try to reference any local vars I get this:
Session expired
Any ideas?