我正在调查当我们的C ++程序在PHP 7.3.4中调用ts_resource(0)时发生的崩溃。
代码是由一个离开公司的开发人员编写的,而我对PHP的了解很少。原始代码是为PHP 5.3编写的,并且已经运行了好几年,但是当PHP升级到7.3.4时,我们的程序开始间歇性崩溃。 我发现崩溃是由对tsrm_get_ls_cache()的调用导致的,该调用返回nullptr。我添加了对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));
...
如果有人可以提出资源分配失败的任何原因,我将非常感激。
答案 0 :(得分:0)
您是否尝试使用TSRMLS_CACHE_UPDATE而不是ZEND_TSRMLS_CACHE_UPDATE(注意ZEND_前缀)?
因此,据我了解,TSRMLS_CACHE_DEFINE应该为每个编译单元设置一次。 应该将TSRMLS_CACHE_EXTERN包含在其他文件中,并在适当时调用TSRMLS_CACHE_UPDATE。