2017-07-06 20 views
2

セグメンテーションを起動しないでスレッド内のメモリをemallocできないのはhttps://github.com/php/php-src/blob/master/Zend/zend_alloc.c#L2409です。PHP拡張モジュールのスレッドからemallocを使用しているときのSegfault

スレッドセーフバージョンのPHP(ZTS)で実行している場合のみ、segfaultが発生します(皮肉なことに)。

プレーンなNTSビルドで実行すると、すべて正常に動作します。

問題を再現するために使用できるコードがいくつかあります(私は拡張機能の作成を簡単にするためにphp-cppを使用しています)。

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; 
} 
} 

ヘッダ:

#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クラスは、試験中におけるemallocによって引き起こさセグメンテーション違反、()スロー:\

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

答えて

2

私の答えはかなり明白かもしれませんが、ちょうど使用しないでくださいemallocと他のすべてのphp/zendメソッドはPHPスレッドの外にあります。 ZTSがオンかオフかに関係なく、コードが失敗します。アプリケーションがクラッシュしている行を見てみましょう:

if (UNEXPECTED(AG(mm_heap)->use_custom_heap)) 

ZTSが呼び出し元のスレッドがへのPHPのスレッドとして適切に初期化されていなかったので、まっすぐセグメンテーション違反があるだろうになるとAGが

#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 

として宣言されていますTSRMG(スレッドセーフリソースマネージャ)を使用すると、ZTSがオフの場合、グローバル変数を変更する競合条件が発生します。

+0

ありがとうございました!しかし、私はどのように正確にスレッドをphpスレッドとして登録することができますかを知りたいのです。単にtsrm_startupを呼び出すだけではうまくいかないようです。 – Danogentili

+0

@Danogentiliあなたは単純にそうしません。私はあなたが自分のスレッドをPHPスレッドとして初期化しても、PHPスレッドを元のスレッドに渡すことはできないと考えています。また、PHPオブジェクトを使用し、実際のP​​HPスレッドの外でPHP関数を呼び出すことは、おそらく悪い考えです。なぜあなたはこれをやりますか? PHPの拡張を書くときは、できるだけ言語の枠を越えることをお勧めします。 – VTT

+0

整数をパラメータとして渡しながら、特定のPHPコールバックを呼び出す必要があります。私は何とかphp pthreads拡張(https://github.com/krakjoe/pthreads)のコードを使用して考えていましたが、スレッドをどのように管理するのかまだ分かりません。 – Danogentili

関連する問題