Matt Sanders
2012-Jul-19 22:43 UTC
Detecting unicorn / defining after_fork after master startup
Hey everyone, Working on an engine for rails that needs specialized behavior with forking and I had a couple questions. 1. What is the best way to determine whether the app is indeed running inside a unicorn server? Most of the attempts I can find to detect check to see if the main modules for Unicorn are defined, but this really only checks to see that Unicorn is present, not that you are using it. I know a lot of shops may use Unicorn in production but something else for local development. Is there something equivalent to the IN_PHUSION_PASSENGER constant that passenger defines? 2. Is there an established way for adding an after_fork hook after Unicorn has already started up? I''m aware of the ability to do this via the config file but I don''t want my users to have to add something to their unicorn config file. Is there an equivalent to passenger''s PhusionPassenger.on_event(:starting_worker_process) method? Thanks! -Matt
Ben Somers
2012-Jul-19 22:55 UTC
Detecting unicorn / defining after_fork after master startup
> 1. What is the best way to determine whether the app is indeed running > inside a unicorn server?I actually wound up just setting an environment variable for this. I manage unicorn through an init.d, and just export UNICORN=true before it starts up the server. We have the exact scenario you describe, Unicorn in production and Passenger on our dev machines.> 2. Is there an established way for adding an after_fork hook after > Unicorn has already started up?I just recently had to solve this problem for my team. In my case, I''ve got multiple applications getting their unicorn configs managed through chef, and so didn''t want to fill the chef with app-specific switches. Since the unicorn config file is just ruby code, I just have my config files check the app directory for a unicorn directory containing before_fork.rb and after_fork.rb files and load the files if they exist. It doesn''t register the hooks after Unicorn starts, but it does let you define them outside of the config file.
Matt Sanders
2012-Jul-19 22:59 UTC
Detecting unicorn / defining after_fork after master startup
Ben, Thanks for your thoughtful comments. The engine I''m writing will be used by users outside of our organization so unfortunately I won''t have any control over their environment or config files - I''m looking to get as close to zero-config as I can through app server detection. Thanks, -Matt
Eric Wong
2012-Jul-19 23:13 UTC
Detecting unicorn / defining after_fork after master startup
Matt Sanders <matt at modal.org> wrote:> 1. What is the best way to determine whether the app is indeed running > inside a unicorn server?Unicorn.listener_names will return a non-empty array of listener addresses.> 2. Is there an established way for adding an after_fork hook after > Unicorn has already started up?Nothing that I know of.> I''m aware of the ability to do this via the config file but I don''t > want my users to have to add something to their unicorn config file. > Is there an equivalent to passenger''s > PhusionPassenger.on_event(:starting_worker_process) method?Lately, I''ve been favoring the following pattern instead: def initialize @init_pid = $$ ... end def initialize_child_fork @init_pid = $$ ... end def call(env) initialize_child_fork if @init_pid != $$ ... end The overhead is negligible and works regardless of server (even in non-HTTP servers somebody may write). I really don''t like code that would need to special case for all sorts of servers: foo_for_passenger if defined?(PhusionPassenger) foo_for_unicorn if defined?(Unicorn) foo_for_something_fastcgi if defined?(SomethingFastCGI) foo_for_something_scgi if defined?(SomethingSCGI) foo_for_something_else_that_forks if defined?(YetAnotherForkingRackServer) foo_for_something_else if defined?(SomethingElse) ...
Matt Sanders
2012-Jul-21 19:42 UTC
Detecting unicorn / defining after_fork after master startup
Eric, Thanks! I definitely agree in general with that pattern. In this case I''d ideally like some activity on the forked child before the next request cycle - that is, if the forked child doesn''t serve any requests for a little bit, I''d still like my behavior to be initialized. Do you know of a way to get this behavior without a direct after fork hook? Thanks for your help! -Matt On Thu, Jul 19, 2012 at 6:13 PM, Eric Wong <normalperson at yhbt.net> wrote:> Matt Sanders <matt at modal.org> wrote: >> 1. What is the best way to determine whether the app is indeed running >> inside a unicorn server? > > Unicorn.listener_names will return a non-empty array of listener > addresses. > >> 2. Is there an established way for adding an after_fork hook after >> Unicorn has already started up? > > Nothing that I know of. > >> I''m aware of the ability to do this via the config file but I don''t >> want my users to have to add something to their unicorn config file. >> Is there an equivalent to passenger''s >> PhusionPassenger.on_event(:starting_worker_process) method? > > Lately, I''ve been favoring the following pattern instead: > > def initialize > @init_pid = $$ > ... > end > > def initialize_child_fork > @init_pid = $$ > ... > end > > def call(env) > initialize_child_fork if @init_pid != $$ > ... > end > > The overhead is negligible and works regardless of server (even in > non-HTTP servers somebody may write). I really don''t like code > that would need to special case for all sorts of servers: > > foo_for_passenger if defined?(PhusionPassenger) > foo_for_unicorn if defined?(Unicorn) > foo_for_something_fastcgi if defined?(SomethingFastCGI) > foo_for_something_scgi if defined?(SomethingSCGI) > foo_for_something_else_that_forks if defined?(YetAnotherForkingRackServer) > foo_for_something_else if defined?(SomethingElse) > ... > _______________________________________________ > Unicorn mailing list - mongrel-unicorn at rubyforge.org > http://rubyforge.org/mailman/listinfo/mongrel-unicorn > Do not quote signatures (like this one) or top post when replying
Eric Wong
2012-Jul-22 21:20 UTC
Detecting unicorn / defining after_fork after master startup
Matt Sanders <matt at modal.org> wrote:> On Thu, Jul 19, 2012 at 6:13 PM, Eric Wong <normalperson at yhbt.net> wrote: > > Matt Sanders <matt at modal.org> wrote: > >> 2. Is there an established way for adding an after_fork hook after > >> Unicorn has already started up? > > > > Nothing that I know of. > > > >> I''m aware of the ability to do this via the config file but I don''t > >> want my users to have to add something to their unicorn config file. > >> Is there an equivalent to passenger''s > >> PhusionPassenger.on_event(:starting_worker_process) method? > > > > Lately, I''ve been favoring the following pattern instead:(top-posting corrected)> Thanks! I definitely agree in general with that pattern. In this case > I''d ideally like some activity on the forked child before the next > request cycle - that is, if the forked child doesn''t serve any > requests for a little bit, I''d still like my behavior to be > initialized.Yes, that sucks. I''ll often just throw some requests at the child just to start something up if I need it, or initiate a separate daemon.> Do you know of a way to get this behavior without a direct after fork hook?No, unfortunately not. I have considered petitioning for something along the lines of pthread_atfork() in Ruby, but pthread_atfork() itself also has unfortunate drawbacks (it makes fork() async-signal un-safe, and thus _Fork() will be introduced in the next version of POSIX).
Apparently Analagous Threads
- AMQP and Unicorn (mq gem)
- Re: [PATCH nbdkit 1/2] server: Add .after_fork callback, mainly for plugins to create threads.
- [PATCH nbdkit 2/2] vddk: Defer library initialization to .after_fork().
- Re: [PATCH nbdkit 2/2] vddk: Defer library initialization to .after_fork().
- after_fork - ActiveRecord::AdapterNotSpecified