From e4947cb9ef56a9d98985237759b3b3687b0ead20 Mon Sep 17 00:00:00 2001 From: Neil Booth Date: Sat, 25 Mar 2017 12:54:35 +0900 Subject: [PATCH] Sanitize the maximum number of sessions Reduce the maximum number of sessions to permit if running with a tight rlimit, to avoid hitting open file limits. Log when doing so. Closes #158 --- server/env.py | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/server/env.py b/server/env.py index bbba097..dbbc78d 100644 --- a/server/env.py +++ b/server/env.py @@ -8,6 +8,7 @@ '''Class for handling environment configuration and defaults.''' +import resource from collections import namedtuple from ipaddress import ip_address from os import environ @@ -60,7 +61,7 @@ class Env(LoggedClass): # Server limits to help prevent DoS self.max_send = self.integer('MAX_SEND', 1000000) self.max_subs = self.integer('MAX_SUBS', 250000) - self.max_sessions = self.integer('MAX_SESSIONS', 1000) + self.max_sessions = self.sane_max_sessions() self.max_session_subs = self.integer('MAX_SESSION_SUBS', 50000) self.bandwidth_limit = self.integer('BANDWIDTH_LIMIT', 2000000) self.session_timeout = self.integer('SESSION_TIMEOUT', 600) @@ -118,6 +119,20 @@ class Env(LoggedClass): raise self.Error('cannot convert envvar {} value {} to an integer' .format(envvar, value)) + def sane_max_sessions(self): + '''Return the maximum number of sessions to permit. Normally this + is MAX_SESSIONS. However, to prevent open file exhaustion, ajdust + downwards if running with a small open file rlimit.''' + env_value = self.integer('MAX_SESSIONS', 1000) + nofile_limit = resource.getrlimit(resource.RLIMIT_NOFILE)[0] + # We give the DB 250 files; allow ElectrumX 100 for itself + value = max(0, min(env_value, nofile_limit - 350)) + if value < env_value: + self.log_warning('lowered maximum seessions from {:,d} to {:,d} ' + 'because your open file limit is {:,d}' + .format(env_value, value, nofile_limit)) + return value + def check_report_host(self, host): try: ip = ip_address(host)