1

I got a problem with Apache and PHP7 on Debian... It is automatically configured by apt... my scripts are making a lot of calculating with a lot of memory used (limit - 512MB). But I noticed that every time I run the script with different parameters, /usr/sbin/apache2 -k start is using more and more memory... it seems that it's not being freed properly. Any ideas how to fix it? Or how to get to what exactly causes it?

The problem is serious and ends up in mmap() failed: [12] Cannot allocate memory in Apache and PHP Fatal error: Out of memory in PHP. With 100% of overall memory used (that is never freed) and inability to do anything more.

It doesn't seem to kill new spawned processes after connection...

PID USER      PRI  NI  VIRT   RES   SHR S CPU% MEM%   TIME+  Command
12123 www-data   20   0  369M  117M  7272 S  0.0  *6.0*  0:18.40 /usr/sbin/apache2 -k start
12132 www-data   20   0  357M  105M  7272 S  0.0  *5.4*  0:17.96 /usr/sbin/apache2 -k start
12122 www-data   20   0  333M 84296  7860 S  0.0  *4.2*  0:18.35 /usr/sbin/apache2 -k start
12133 www-data   20   0  311M 61160  7272 S  0.0  *3.1* 0:08.00 /usr/sbin/apache2 -k start
12131 www-data   20   0  293M 42732  7272 S  0.0  *2.1*  0:17.70 /usr/sbin/apache2 -k start
12134 www-data   20   0  291M 40676  7272 S  0.0  *2.0*  0:08.32 /usr/sbin/apache2 -k start
12124 www-data   20   0  275M 25040  7900 S  0.0  *1.2*  0:16.19 /usr/sbin/apache2 -k start
12125 www-data   20   0  265M 13084  6768 S  0.0  *0.7*  0:00.01 /usr/sbin/apache2 -k start
12128 www-data   20   0  265M 13060  6708 S  0.0  *0.7*  0:00.01 /usr/sbin/apache2 -k start
12126 www-data   20   0  265M  9468  3332 S  0.0  *0.5*  0:00.00 /usr/sbin/apache2 -k start

The value between * is MEM% from htop. Every new calculation new process spawns. And others are using more and more memory...

apache2 -l

Compiled in modules:
  core.c
  mod_so.c
  mod_watchdog.c
  http_core.c
  mod_log_config.c
  mod_logio.c
  mod_version.c
  mod_unixd.c

a2query -M

prefork
Flash Thunder
  • 261
  • 3
  • 13
  • Which MPM are you running? prefork, or worker? You are not using the worker MPM with mod_php, or are you? The simplest solution might be a change to php-fpm (which is generally advisable these days IMHO). – s1lv3r Feb 09 '18 at 19:34
  • It seems that default installation configured it as prefork. Would rather not to change it to php-fpm... and it doesn't support PHP7. – Flash Thunder Feb 09 '18 at 19:46
  • I think what you see is expected behavior so far with prefork. It spawns child processes, which stay alive until they are recycled (MaxConnectionsPerChild is reached). You can read more about the inner workings of the prefork MPM [here](https://httpd.apache.org/docs/2.4/en/mod/prefork.html). Unless you have a real performance problem which you need to solve, you probably don't have to change anything. If you have a real problem (low-memory, OOM kicking in) you may need to tweak your config, (especially MaxRequestWorkers) or change to another MPM. – s1lv3r Feb 09 '18 at 20:02
  • The problem is serious and ends up in `mmap() failed: [12] Cannot allocate memory` Apache error... and `PHP Fatal error: Out of memory `. With 100% of overall memory used that is never being freed. – Flash Thunder Feb 09 '18 at 20:05
  • Oh and I tried to set MaxConnectionsPerChild to 1 but it did not change anything. Still doesn't free any memory. – Flash Thunder Feb 09 '18 at 22:11

1 Answers1

0

What you're seeing is normal behaviour when using mod_php with apache2 prefork.

When a php script is run in a preforked process there something like a "PHP memory buffer" in that preforked apache process. It grows whenever the running script demands more memory than is already allocated, but only shrinks when the preforked process is recycled (i.e. restarted).

You can mitigate that issue by setting ServerLimit and MaxClients to (system memory / php memory_limit) which will lead to no more than that number of preforked processes. That number multiplied by your php memory_limit will fit into memory.

You can also set MaxRequestsPerChild 1, but this will have a really bad effect on performance.

In the long-term you should probably migrate to php-fpm and carefully plan the maximum number of php processes with their memory consumption.

Andreas Rogge
  • 2,853
  • 11
  • 24
  • As I wrote in comment to my question... `MaxRequestsPerChild 1` did nothing. Totally nothing. Maybe I put it in wrong place? `/etc/apache2/apache2.conf` at top. I can't set PHP memory limit to lower than I set, as the script needs it. I don't need many connections, so i set `ServerLimit` and `MaxClients` to 10. Mostly the server will be used by one person at a time. But still your answer did not fix the problem... Maybe it has something to do with `keep-alive`? As requests are being sent by ajax? – Flash Thunder Feb 10 '18 at 08:38
  • I also tried `MaxMemFree 2048` ... without success. – Flash Thunder Feb 10 '18 at 08:43
  • You wrote that you configured `MaxConnectionsPerChild` not `MaxRequestsPerChild`. – Andreas Rogge Feb 10 '18 at 09:54
  • If you configure ServerLimit/MaxClients to 10 and PHP's memory_limit to 512 MB, you'll need at least 5 GB of memory. Is your machine sized accordingly? – Andreas Rogge Feb 10 '18 at 09:55
  • it's the same option... from documentation: `Compatibility: Available Apache HTTP Server 2.3.9 and later. The old name MaxRequestsPerChild is still supported.` ... and about second comment... it's the limit... and most of that memory is being freed by PHP... on biggest calculation the memory not being freed is about `5%` of available on the server. 10x5x1 = 50%. But I can see in `htop` that `MaxConnectionsPerChild` simply doesn't work. `MaxRequestsPerChild` neither. It still uses same process and cumulates it's memory usage... until running out of it globally. – Flash Thunder Feb 10 '18 at 13:02
  • PS. It does cycle through available processes, but doesn't free memory of any of them... – Flash Thunder Feb 10 '18 at 13:10
  • But does it free up memory after apachectl graceful? That should recycle every preforked process once it is idle. If at least this works, we just need to find out why `MaxRequestsPerChild` / `MaxConnectionsPerChild` doesn't work in your case. – Andreas Rogge Feb 10 '18 at 13:41
  • You mean after restarting / stopping server? yes, it does. – Flash Thunder Feb 10 '18 at 13:49
  • So the question is: why doesn't apache recycle the processes itself? – Andreas Rogge Feb 10 '18 at 20:20
  • I made some more tests with settings: `ServerLimit 1`, `MaxClients 1`, `MaxConnectionsPerChild 1`, `KeepAlive Off`; `htop` shows only one process of `apache2`, but still not freeing memory... I really have no idea what to do now to make it work properly :-( – Flash Thunder Feb 13 '18 at 12:06