首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在PHP扩展中使用线程中的emalloc时出现Segfault

在PHP扩展中使用线程中的emalloc时出现Segfault
EN

Stack Overflow用户
提问于 2017-07-07 01:52:08
回答 1查看 412关注 0票数 2

我不能在不触发https://github.com/php/php-src/blob/master/Zend/zend_alloc.c#L2409段错误的情况下释放线程内的任何数量的内存。

只有在PHP (ZTS)的线程安全版本上运行时,(具有讽刺意味的)才会发生段错误。

当在普通的NTS版本上运行时,一切工作正常。

下面是一些可用于重现该问题的代码(我使用php-cpp来简化扩展的创建)。

代码语言:javascript
复制
void* test(void* wrapper){
    emalloc(sizeof(Php::Value));
    return NULL;
}

void VoIP::__construct()
{
    pthread_t a;    
    pthread_create(&a, NULL, test, this);
}
extern "C" {
PHPCPP_EXPORT void *get_module()
{
    static Php::Extension extension("php-libtgvoip", "1.0");

    Php::Class<VoIP> voip("VoIP");

    voip.method<&VoIP::__construct>("__construct", Php::Public | Php::Final);
    Php::Namespace danog("danog");
    Php::Namespace MadelineProto("MadelineProto");

    MadelineProto.add(std::move(voip));
    danog.add(std::move(MadelineProto));
    extension.add(std::move(danog));

    return extension;
}
}

标题:

代码语言:javascript
复制
#include <php.h>
#include <php_ini.h>
#include <ext/standard/info.h>
#include <phpcpp.h>

class VoIP : public Php::Base {
public:

    void __construct();

}

实例化\danog\MadelineProto\VoIP类抛出了一个段错误,这是由test()中的emalloc引起的:

代码语言:javascript
复制
Thread 2 "php" received signal SIGSEGV, Segmentation fault.
[Switching to Thread 0x7fffe91ff700 (LWP 4267)]
0x0000555555cfc7ed in _emalloc (size=32, __zend_filename=0x7fffed9c88a8 "main.cpp", __zend_lineno=30, __zend_orig_filename=0x0, __zend_orig_lineno=0)
    at /root/php-src/Zend/zend_alloc.c:2409
2409            if (UNEXPECTED(AG(mm_heap)->use_custom_heap)) {
(gdb) backtrace
#0  0x0000555555cfc7ed in _emalloc (size=32, __zend_filename=0x7fffed9c88a8 "main.cpp", __zend_lineno=30, __zend_orig_filename=0x0, __zend_orig_lineno=0)
    at /root/php-src/Zend/zend_alloc.c:2409
#1  0x00007fffed94e80e in test (wrapper=0x555556a73310) at main.cpp:30
#2  0x00007ffff572a494 in start_thread (arg=0x7fffe91ff700) at pthread_create.c:333
#3  0x00007ffff206eaff in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:97
(gdb)

完整的源代码可以在@ https://github.com/danog/php-libtgvoip中找到

EN

回答 1

Stack Overflow用户

发布于 2017-07-07 02:21:17

我的答案可能很明显,但不要在php线程之外使用emalloc和所有其他php/zend方法。无论ZTS是打开还是关闭,您的代码都会失败。看一下应用程序崩溃的代码行:

代码语言:javascript
复制
if (UNEXPECTED(AG(mm_heap)->use_custom_heap)) 

AG被声明为

代码语言:javascript
复制
#ifdef ZTS

static int alloc_globals_id;
#define AG(v) ZEND_TSRMG(alloc_globals_id, zend_alloc_globals *, v)

#else

#define AG(v) (alloc_globals.v)
static zend_alloc_globals alloc_globals;

#endif

当ZTS打开时,会有一个直接的段错误,因为调用线程没有正确地初始化为php线程来使用TSRMG (线程安全资源管理器),当ZTS关闭时,会有一个竞争条件来修改全局变量。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/44955838

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档