A significant memory leak has been reported in WordPress 4.9.7 that affects wp_is_stream() in wp-include/functions.php. The issue has been verified on PHP 7.0 and 7.1 used on Luna and Atlas platforms.
Symptoms
Periodically a HTTP request will fail with a 500 error. Upon further examination in /var/log/httpd/error_log, an implausible memory allocation is noted as the cause:
[Fri Jul 20 12:02:59.902112 2018] [php7:error] [pid 18816:tid 140512799483648] [client 178.159.37.70:62120] PHP Fatal error: Allowed memory size of 268435456 bytes exhausted (tried to allocate 11072576711821379 bytes) in … wp-includes/functions.php on line 5231
Cause
PHP7 has a memory leak in stream_get_wrappers() first reported in 2016. It was supposedly resolved, however not entirely. WordPress calls this heavily in response to a security update published in 4.9.7. Some combinations of themes/plugins/request frequency are more apt to trigger the memory leak. A survey noted that approximately 33% of WordPress installs have encountered at least 1 memory leak related to this in the past 24 hours.
Solution
Ultimately the memory leak falls squarely on the PHP dev team. Once a new release of PHP addresses the memory leak fully, it will be installed on the server thus obviating the following hotfix.
WordPress has published a workaround that reduces the number of calls to wp_is_stream(). Edit wp-includes/functions.php and add after the wp_is_stream() function declaration (around line 5230):
if ( false !== strpos( $path, 'file://' ) || false === strpos( $path, '://' ) ) { // can't possibly be a stream return false; }
After altering the function should look like:
function wp_is_stream($path) { if (false !== strpos($path, 'file://') || false === strpos($path, '://')) { // can't possibly be a stream return false; } $wrappers = stream_get_wrappers(); $wrappers_re = '(' . join('|', $wrappers) . ')'; return preg_match("!^$wrappers_re://!", $path) === 1; }