Make memory limits configurable and make them work with passenger
[rails.git] / config / initializers / memory_limits.rb
1 # Setup any specified hard limit on the virtual size of the process
2 if APP_CONFIG.include?('hard_memory_limit') and Process.const_defined?(:RLIMIT_AS)
3   Process.setrlimit Process::RLIMIT_AS, APP_CONFIG['hard_memory_limit']*1024*1024, Process::RLIM_INFINITY
4 end
5
6 # If we're running under passenger and a soft memory limit is
7 # configured then setup some rack middleware to police the limit
8 if APP_CONFIG.include?('soft_memory_limit') and defined?(PhusionPassenger)
9   # Define some rack middleware to police the soft memory limit
10   module OSM
11     class MemoryLimit
12       def initialize(app)
13         @app = app
14       end
15
16       def call(env)
17         # Process this requst
18         status, headers, body = @app.call(env)
19
20         # Restart if we've hit our memory limit
21         if resident_size > APP_CONFIG['soft_memory_limit']
22           Process.kill("USR1", 0)
23         end
24
25         # Return the result of this request
26         [status, headers, body]
27       end
28       private
29       def resident_size
30         # Read statm to get process sizes. Format is
31         #   Size RSS Shared Text Lib Data
32         fields = File.open("/proc/self/statm") do |file|
33           fields = file.gets.split(" ")
34         end
35
36         # Return resident size in megabytes
37         return fields[1].to_i / 256
38       end
39     end
40   end
41
42   # Install the memory limit checker
43   Rails.configuration.middleware.use OSM::MemoryLimit
44 end