4

我正在调查当我们的 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)); ...

如果有人能提出资源分配可能失败的任何原因,我将不胜感激。

4

1 回答 1

0

您是否尝试过使用 TSRMLS_CACHE_UPDATE 而不是 ZEND_TSRMLS_CACHE_UPDATE(注意 ZEND_ 前缀)?

因此,据我所知,每个编译单元应该设置一次 TSRMLS_CACHE_DEFINE。TSRMLS_CACHE_EXTERN 应该包含在其他文件中,并且应该在适当的时候调用 TSRMLS_CACHE_UPDATE。

于 2020-02-14T10:41:20.367 回答