我正在调查当我们的 C++ 程序在 PHP 7.3.4 中调用 ts_resource(0) 时发生的崩溃。
代码是由一个已经离开公司的开发人员编写的,我对 PHP 知之甚少。原始代码是为 PHP 5.3 编写的,多年来一直运行良好,但是当 PHP 升级到 7.3.4 时,我们的程序开始间歇性地崩溃。我发现崩溃是由返回 nullptr 的 tsrm_get_ls_cache() 调用引起的。我添加了对 nullptr 的检查,因此停止了崩溃,但我想知道为什么获取资源的调用返回 nullptr 以及我能做些什么来防止它。我认为问题与内存有关,因为它是间歇性的。
我不确定要显示什么代码,因为我们的代码中对 PHP 的调用很广泛。PHP 是在启用 ZTS 的情况下编译的,因此它是多线程的。
在初始化阶段,线程安全管理器以以下方式启动:
tsrm_startup(128, 1, 0, NULL);
ts_resource(0);
ZEND_TSRMLS_CACHE_UPDATE();
以及每次调用 PHP 代码时调用的 Execute 函数以:
ts_resource(0);
ZEND_TSRMLS_CACHE_UPDATE();
if (tsrm_get_ls_cache() == nullptr)
return false;
ExecuteContext context;
context.pOutputStream = pOutputStream;
SG(server_context) = (void*)&context;
接下来在调用之前对上下文类进行一些初始化
php_request_startup(TSRMLS_C);
当获取资源调用失败时,实际失败是因为malloc失败:在Execute函数开头调用ts_resource(0)调用下面的PHP函数分配新资源:
allocate_new_resource(&thread_resources->next, thread_id);
并且此对 malloc 的调用使分配失败
static void allocate_new_resource(tsrm_tls_entry **thread_resources_ptr, THREAD_T thread_id)
{
(*thread_resources_ptr) = (tsrm_tls_entry *) malloc(sizeof(tsrm_tls_entry));
...
如果有人能提出资源分配可能失败的任何原因,我将不胜感激。