]> git.openstreetmap.org Git - rails.git/blobdiff - config/initializers/memory_limits.rb
Make memory limits configurable and make them work with passenger
[rails.git] / config / initializers / memory_limits.rb
diff --git a/config/initializers/memory_limits.rb b/config/initializers/memory_limits.rb
new file mode 100644 (file)
index 0000000..bab94b0
--- /dev/null
@@ -0,0 +1,44 @@
+# Setup any specified hard limit on the virtual size of the process
+if APP_CONFIG.include?('hard_memory_limit') and Process.const_defined?(:RLIMIT_AS)
+  Process.setrlimit Process::RLIMIT_AS, APP_CONFIG['hard_memory_limit']*1024*1024, Process::RLIM_INFINITY
+end
+
+# If we're running under passenger and a soft memory limit is
+# configured then setup some rack middleware to police the limit
+if APP_CONFIG.include?('soft_memory_limit') and defined?(PhusionPassenger)
+  # Define some rack middleware to police the soft memory limit
+  module OSM
+    class MemoryLimit
+      def initialize(app)
+        @app = app
+      end
+
+      def call(env)
+        # Process this requst
+        status, headers, body = @app.call(env)
+
+        # Restart if we've hit our memory limit
+        if resident_size > APP_CONFIG['soft_memory_limit']
+          Process.kill("USR1", 0)
+        end
+
+        # Return the result of this request
+        [status, headers, body]
+      end
+      private
+      def resident_size
+        # Read statm to get process sizes. Format is
+        #   Size RSS Shared Text Lib Data
+        fields = File.open("/proc/self/statm") do |file|
+          fields = file.gets.split(" ")
+        end
+
+        # Return resident size in megabytes
+        return fields[1].to_i / 256
+      end
+    end
+  end
+
+  # Install the memory limit checker
+  Rails.configuration.middleware.use OSM::MemoryLimit
+end