diff --git a/boot.php b/boot.php index d5972484b..99af7d377 100644 --- a/boot.php +++ b/boot.php @@ -1321,6 +1321,45 @@ class App { return false; } + /** + * @brief Checks if the minimal memory is reached + * + * @return bool Is the memory limit reached? + */ + public function min_memory_reached() { + $min_memory = Config::get('system', 'min_memory', 0); + if ($min_memory == 0) { + return false; + } + + if (!is_readable("/proc/meminfo")) { + return false; + } + + $memdata = explode("\n", file_get_contents('/proc/meminfo')); + + $meminfo = array(); + foreach ($memdata as $line) { + list($key, $val) = explode(":", $line); + $meminfo[$key] = (int)trim(str_replace("kB", "", $val)); + $meminfo[$key] = (int)($meminfo[$key] / 1024); + } + + if (!isset($meminfo['MemAvailable']) OR !isset($meminfo['MemFree'])) { + return false; + } + + $free = $meminfo['MemAvailable'] + $meminfo['MemFree']; + + $reached = ($free < $min_memory); + + if ($reached) { + logger('Minimal memory reached: '.$free.'/'.$meminfo['MemTotal'].' - limit '.$min_memory, LOGGER_DEBUG); + } + + return $reached; + } + /** * @brief Checks if the maximum load is reached * @@ -1381,6 +1420,10 @@ class App { $cmdline = implode($args, " "); + if ($this->min_memory_reached()) { + return; + } + if (get_config('system', 'proc_windows')) { $resource = proc_open('cmd /c start /b ' . $cmdline, array(), $foo, dirname(__FILE__)); } else { diff --git a/include/poller.php b/include/poller.php index 5560b3340..8f9f5aa24 100644 --- a/include/poller.php +++ b/include/poller.php @@ -41,6 +41,10 @@ function poller_run($argv, $argc){ $a->start_process(); + if ($a->min_memory_reached()) { + return; + } + if (poller_max_connections_reached()) { return; } @@ -67,6 +71,11 @@ function poller_run($argv, $argc){ while ($r = poller_worker_process()) { + // Check free memory + if ($a->min_memory_reached()) { + return; + } + // Count active workers and compare them with a maximum value that depends on the load if (poller_too_much_workers()) { return; diff --git a/mod/admin.php b/mod/admin.php index 97d52f14f..250ebbe2a 100644 --- a/mod/admin.php +++ b/mod/admin.php @@ -731,6 +731,7 @@ function admin_page_site_post(App $a) { $timeout = ((x($_POST,'timeout')) ? intval(trim($_POST['timeout'])) : 60); $maxloadavg = ((x($_POST,'maxloadavg')) ? intval(trim($_POST['maxloadavg'])) : 50); $maxloadavg_frontend = ((x($_POST,'maxloadavg_frontend')) ? intval(trim($_POST['maxloadavg_frontend'])) : 50); + $min_memory = ((x($_POST,'min_memory')) ? intval(trim($_POST['min_memory'])) : 0); $optimize_max_tablesize = ((x($_POST,'optimize_max_tablesize')) ? intval(trim($_POST['optimize_max_tablesize'])): 100); $optimize_fragmentation = ((x($_POST,'optimize_fragmentation')) ? intval(trim($_POST['optimize_fragmentation'])): 30); $poco_completion = ((x($_POST,'poco_completion')) ? intval(trim($_POST['poco_completion'])) : false); @@ -816,6 +817,7 @@ function admin_page_site_post(App $a) { set_config('system','ssl_policy',$ssl_policy); set_config('system','maxloadavg',$maxloadavg); set_config('system','maxloadavg_frontend',$maxloadavg_frontend); + set_config('system','min_memory',$min_memory); set_config('system','optimize_max_tablesize',$optimize_max_tablesize); set_config('system','optimize_fragmentation',$optimize_fragmentation); set_config('system','poco_completion',$poco_completion); @@ -1113,6 +1115,7 @@ function admin_page_site(App $a) { '$timeout' => array('timeout', t("Network timeout"), (x(get_config('system','curl_timeout'))?get_config('system','curl_timeout'):60), t("Value is in seconds. Set to 0 for unlimited (not recommended).")), '$maxloadavg' => array('maxloadavg', t("Maximum Load Average"), ((intval(get_config('system','maxloadavg')) > 0)?get_config('system','maxloadavg'):50), t("Maximum system load before delivery and poll processes are deferred - default 50.")), '$maxloadavg_frontend' => array('maxloadavg_frontend', t("Maximum Load Average (Frontend)"), ((intval(get_config('system','maxloadavg_frontend')) > 0)?get_config('system','maxloadavg_frontend'):50), t("Maximum system load before the frontend quits service - default 50.")), + '$min_memory' => array('min_memory', t("Minimal Memory"), ((intval(get_config('system','min_memory')) > 0)?get_config('system','min_memory'):0), t("Minimal free memory in MB for the poller. Needs access to /proc/meminfo - default 0 (deactivated).")), '$optimize_max_tablesize'=> array('optimize_max_tablesize', t("Maximum table size for optimization"), $optimize_max_tablesize, t("Maximum table size (in MB) for the automatic optimization - default 100 MB. Enter -1 to disable it.")), '$optimize_fragmentation'=> array('optimize_fragmentation', t("Minimum level of fragmentation"), ((intval(get_config('system','optimize_fragmentation')) > 0)?get_config('system','optimize_fragmentation'):30), t("Minimum fragmenation level to start the automatic optimization - default value is 30%.")), diff --git a/view/templates/admin_site.tpl b/view/templates/admin_site.tpl index 196bc479b..6a3c3fbcd 100644 --- a/view/templates/admin_site.tpl +++ b/view/templates/admin_site.tpl @@ -118,7 +118,6 @@ {{include file="field_input.tpl" field=$proxy}} {{include file="field_input.tpl" field=$proxyuser}} {{include file="field_input.tpl" field=$timeout}} - {{include file="field_input.tpl" field=$maxloadavg}} {{include file="field_input.tpl" field=$maxloadavg_frontend}} {{include file="field_input.tpl" field=$optimize_max_tablesize}} {{include file="field_input.tpl" field=$optimize_fragmentation}} @@ -146,6 +145,8 @@