前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >PHP内存分配超过限制的退出流程

PHP内存分配超过限制的退出流程

作者头像
桶哥
发布2020-07-15 15:35:07
1.7K0
发布2020-07-15 15:35:07
举报
文章被收录于专栏:PHP饭米粒

我们知道,在PHP的世界里,如果我们要申请一块内存 ,但是没有申请到,那么就会导致fatal级别的错误。我们来测试下:

代码语言:javascript
复制
<?php

ini_set('memory_limit','1M');

$str = str_repeat('a', 2 * 1024 * 1024);

执行结果如下:

代码语言:javascript
复制
[root@a896c4eb1fc4 library]# php oom.php
PHP Fatal error:  Allowed memory size of 2097152 bytes exhausted at /root/php-src/Zend/zend_string.h:144 (tried to allocate 2097184 bytes) in /root/codeDir/phpCode/library/oom.php on line 5

Fatal error: Allowed memory size of 2097152 bytes exhausted at /root/php-src/Zend/zend_string.h:144 (tried to allocate 2097184 bytes) in /root/codeDir/phpCode/library/oom.php on line 5
[root@a896c4eb1fc4 library]#

可以看到,这里抛出了fatal的错误。

可能有小伙伴会觉得很正常,既然内存用完了,就应该报错,然后终止程序的执行才对。况且,大部分的PHP程序都是FPM的模型,就算这个PHP进程挂了,也不会影响后续的请求。但是,这对于基于CLI的常驻内存的PHP程序就是致命的了,一旦超过了内存限制,就会导致整个服务挂了,哪怕这次内存申请是很不重要的,也会导致整个VM的崩溃。比如说,我想要分配一个内存,但是不确定要分配多少,所以我只能够去尝试着分配。比如说第一次尝试分配2M,第二次尝试分配1M。然而,第一次申请的内存太多了,达到了限制,直接就是fatal了,就没有后续尝试分配1M的事情了。所以,这就会导致,我们不敢百分之百的去使用内存资源,因为一旦我们不小心申请的内存超过了限制,程序就会直接奔溃,没有任何拯救的余地。

我们来打个类似的比方,我们写一个Web服务器,我们要去accept连接,但是,这个时候返回了一个Too many open files的错误码。这个时候,我们是直接让程序exit吗?还是sleep一会儿,然后再去accept连接?显然是后者。所以,我们写长生命周期的脚本,需要把内存限制往大了开。

我们现在来看一下PHP内核是如何处理内存达到限制的情况的。重点在函数zend_mm_safe_error里面:

代码语言:javascript
复制
static ZEND_COLD ZEND_NORETURN void zend_mm_safe_error(zend_mm_heap *heap,
	const char *format,
	size_t limit,
#if ZEND_DEBUG
	const char *filename,
	uint32_t lineno,
#endif
	size_t size)
{

	heap->overflow = 1;
	zend_try {
		zend_error_noreturn(E_ERROR,
			format,
			limit,
#if ZEND_DEBUG
			filename,
			lineno,
#endif
			size);
	} zend_catch {
	}  zend_end_try();
	heap->overflow = 0;
	zend_bailout();
	exit(1);
}

在调用str_repeat时候,如果内存不够,zend_mm_safe_error就会被调用。我们发现,在这个函数里面,调用了zend_bailout(),这就会导致PHP的执行流回到php_execute_script这个函数的zend_try里面,然后,PHP脚本退出执行。

所以,我们发现,只要有一次申请的PHP内存累积到了我们设置的限制,就没有任何拯救的余地了,进程直接退出了。

----------伟大的分割线-----------

本文由 coding huang 授权 饭米粒 发布,转载请注明本来源信息和以下的二维码(长按可识别二维码关注)

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-07-13,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 PHP饭米粒 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档