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;
}
Important: memory leak in WordPress 4.9.7
Tagged on: