【问题标题】:php7 oauth illegal memory allocationphp7 oauth非法内存分配
【发布时间】:2016-07-06 12:36:12
【问题描述】:

简介

在复杂的 Web 应用程序中运行时,生成的 php7 进程在使用 oauth 模块时尝试分配非法内存量(18446744069414584466 字节)。 fpm manager 重启后,此代码被触发 2-5 次后出现错误:

$oauthClient = new \OAuth($consumerKey, $consumerSecret, OAUTH_SIG_METHOD_HMACSHA1, OAUTH_AUTH_TYPE_AUTHORIZATION);
$oauthClient->disableSSLChecks();
$oauthClient->setToken($token, $tokenSecret);
$oauthClient->fetch($callUrl, $strPostData, $method, $headers);

错误信息

*20 FastCGI sent in stderr: "PHP message: PHP Fatal error:  Allowed memory size of 536870912 bytes exhausted (tried to allocate 18446744069414584466 bytes)

说明

错误信息中提到的受影响的行是oauth客户端的fetch方法

$oauthClient->fetch($callUrl, $strPostData, $method, $headers);

我尝试通过在循环中执行相关代码并观察一段时间内的内存使用情况来隔离相关代码。使用和分配的内存量似乎随着时间的推移稳定增长,但没有预期的那么快(可能只是 oauthClient 缓存响应)

独立

代码

<?php

$strPostData = '';
$method = 'GET';
$consumerKey = '<consumerKey>';
$consumerSecret = '<consumerSecret>';
$token = '<token>';
$tokenSecret = '<tokenSecret>';
$url = '<url>';

$headers = array('accept' => 'application/json');
$callUrl = $url;

if ($method === 'POST' || $method === 'PUT') {
    $headers['Content-Type'] = 'application/json';
}

$oauthClient = new \OAuth($consumerKey, $consumerSecret, OAUTH_SIG_METHOD_HMACSHA1, OAUTH_AUTH_TYPE_AUTHORIZATION);
$oauthClient->disableSSLChecks();
$oauthClient->setToken($token, $tokenSecret);

do {
        $oauthClient->fetch($callUrl, $strPostData, $method, $headers);
        $response = $oauthClient->getLastResponse();
        fwrite(STDOUT, 'Allocated Memory: '. memory_get_usage(false) . PHP_EOL);
        fwrite(STDOUT, 'Used Memory: '. memory_get_usage(true) . PHP_EOL);
} while (true);
?>

输出

Allocated Memory: 236920
Used Memory: 262144
...
Allocated Memory: 263168
Used Memory: 524288
...
Allocated Memory: 289504
Used Memory: 524288
...
Used Memory: 524288
Allocated Memory: 331888
...
Allocated Memory: 395976
Used Memory: 524288
...
Allocated Memory: 428600
Used Memory: 524288
...

核心和模块版本

Core: 7.0.8-3+deb.sury.org~trusty+1
date: 7.0.8-3+deb.sury.org~trusty+1
libxml: 7.0.8-3+deb.sury.org~trusty+1
openssl: 7.0.8-3+deb.sury.org~trusty+1
pcre: 7.0.8-3+deb.sury.org~trusty+1
zlib: 7.0.8-3+deb.sury.org~trusty+1
filter: 7.0.8-3+deb.sury.org~trusty+1
hash: 1.0
pcntl: 7.0.8-3+deb.sury.org~trusty+1
Reflection: 7.0.8-3+deb.sury.org~trusty+1
SPL: 7.0.8-3+deb.sury.org~trusty+1
session: 7.0.8-3+deb.sury.org~trusty+1
standard: 7.0.8-3+deb.sury.org~trusty+1
mysqlnd: mysqlnd 5.0.12-dev - 20150407 - $Id: 241ae00989d1995ffcbbf63d579943635faf9972 $
PDO: 7.0.8-3+deb.sury.org~trusty+1
xml: 7.0.8-3+deb.sury.org~trusty+1
bcmath: 7.0.8-3+deb.sury.org~trusty+1
calendar: 7.0.8-3+deb.sury.org~trusty+1
ctype: 7.0.8-3+deb.sury.org~trusty+1
curl: 7.0.8-3+deb.sury.org~trusty+1
dom: 20031129
mbstring: 7.0.8-3+deb.sury.org~trusty+1
fileinfo: 1.0.5
ftp: 7.0.8-3+deb.sury.org~trusty+1
gd: 7.0.8-3+deb.sury.org~trusty+1
gettext: 7.0.8-3+deb.sury.org~trusty+1
iconv: 7.0.8-3+deb.sury.org~trusty+1
json: 1.4.0
exif: 1.4 $Id: 8bdc0c8f27c2c9dd1f7551f1f9fe3ab57a06a4b1 $
mysqli: 7.0.8-3+deb.sury.org~trusty+1
OAuth: 2.0.2
pdo_mysql: 7.0.8-3+deb.sury.org~trusty+1
pdo_sqlite: 7.0.8-3+deb.sury.org~trusty+1
Phar: 2.0.2
posix: 7.0.8-3+deb.sury.org~trusty+1
readline: 7.0.8-3+deb.sury.org~trusty+1
shmop: 7.0.8-3+deb.sury.org~trusty+1
SimpleXML: 7.0.8-3+deb.sury.org~trusty+1
soap: 7.0.8-3+deb.sury.org~trusty+1
sockets: 7.0.8-3+deb.sury.org~trusty+1
sqlite3: 0.7-dev
ssh2: 0.13-dev
sysvmsg: 7.0.8-3+deb.sury.org~trusty+1
sysvsem: 7.0.8-3+deb.sury.org~trusty+1
sysvshm: 7.0.8-3+deb.sury.org~trusty+1
tokenizer: 7.0.8-3+deb.sury.org~trusty+1
wddx: 7.0.8-3+deb.sury.org~trusty+1
xmlreader: 7.0.8-3+deb.sury.org~trusty+1
xmlwriter: 7.0.8-3+deb.sury.org~trusty+1
xsl: 7.0.8-3+deb.sury.org~trusty+1
zip: 1.13.3
Zend OPcache: 7.0.8-3+deb.sury.org~trusty+1

【问题讨论】:

  • 你有什么办法吗?我对 pecl oauth 和 PHP 7.0.4-7ubuntu2.1(在 Ubuntu 16.04 上)有同样的问题。高得离谱的内存分配:允许的内存大小为 134217728 字节已用尽(试图分配 18446744069414591624 字节)
  • 我还要补充一点,我正在使用 apache 遇到这种情况,如果我在服务器重新启动后再次保存文件,代码通常可以正常工作。
  • 不,不幸的是,我们不得不降级到 php5.6,如果我查看最近在基本功能中发现并修复的错误数量 (php.net/ChangeLog-7.php#7.0.7),我不知道'认为它无论如何都不能真正用于生产,例如: json_encode()/json_decode()/ json_utf8_to_utf16() 中的整数溢出,nl2br() 中的整数溢出
  • PHP 试图分配大得离谱的内存通常反映了 PHP 中的错误,而不是实际需要如此大的分配。

标签: oauth-2.0 php-7


【解决方案1】:

我遇到了类似的问题,并将其归结为在启用 opcache 的情况下使用 oauth 扩展的问题。对于我遇到的确切情况,实际上存在一个针对 php 的错误 - https://bugs.php.net/bug.php?id=73310。在完全解决之前,我们找到了解决此问题的潜在解决方法,将利用 opcache 的 oauth 扩展名的文件列入黑名单可以清除异常。

您可以使用 opcache.blacklist-filename 选项将 opcache 的文件列入黑名单 - http://php.net/manual/en/opcache.configuration.php#ini.opcache.blacklist-filename

  • 在您的服务器上添加一个 txt 文件,其中每个文件的完整路径都包含在单独的行中
  • 在编辑模式下打开 opcache.ini(例如 sudo vi /etc/php/7.0/mods-available/opcache.ini)
  • 编辑 opcache.blacklist-filename 选项以指向您使用列入黑名单的文件创建的 txt 文件
  • 如果您使用的是 fpm,请重新启动它

【讨论】:

  • 哇,原来如此。我收到“PHP 致命错误:允许的内存大小”...错误消息...
【解决方案2】:

@shlm 的替代方法是一起禁用 opcache。

在我的项目中,响应时间的减少是最小的,所以对我来说,如果我将文件列入黑名单或禁用 opcache,这并没有什么显着差异。

我在 .htaccess 文件中使用以下行禁用了它。

php_flag opcache.enable Off

【讨论】:

    【解决方案3】:

    不知从何而来,这对我来说就像魅力一样

    $this->oauth->fetch($endpoint, [], 'GET', ['Accept' => 'application/json']);
    

    变成

    $this->oauth->fetch($endpoint, ['fix'], 'GET', ['Accept' => 'application/json']);
    

    可以,只填第二个参数,不要留空

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-10-11
      • 1970-01-01
      • 2016-01-26
      • 2013-11-21
      • 2011-02-08
      • 2016-04-29
      • 2017-07-15
      相关资源
      最近更新 更多