2

I cannot emalloc any amount of memory inside of a thread without triggering a segfault at https://github.com/php/php-src/blob/master/Zend/zend_alloc.c#L2409.

The segfault occurs (ironically) only when running on a thread-safe version of PHP (ZTS).

When running on a plain NTS build, everything works normally.

Here's some code that can be used to reproduce the issue (I'm using php-cpp to simplify the creation of the extension).

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

Header:

#include <php.h>
#include <php_ini.h>
#include <ext/standard/info.h>
#include <phpcpp.h>

class VoIP : public Php::Base {
public:

    void __construct();

}

Instantiation of the \danog\MadelineProto\VoIP class throws a segfault, caused by the emalloc in test():

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)

The full source code can be found @ https://github.com/danog/php-libtgvoip

1 Answer 1

2

My answer might be rather obvious, but just don't use emalloc and all the other php/zend methods outside of php threads. Your code fails regardless of whether ZTS is on or off. Take a look at line where application is crashing:

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

AG is declared as

#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

When ZTS is on there will be a straight segfault because the calling thread was not initialized properly as php thread to use TSRMG (Thread Safe Resource Manager), when ZTS is off there will be a race condition to modify a global variable.

Sign up to request clarification or add additional context in comments.

7 Comments

Thank you for the answer! However, I would like to know how exactly can I register a thread as a php thread: simply calling tsrm_startup does not seem to work.
@Danogentili You simply don't. I suspect that even if you initialize your own thread as php thread you won't be able to pass php objects from it to original thread. Also it is probably a bad idea to use php objects and call php functions outside of real php thread. Why would you do this? When writing php extension it is preferred to cross the language border as little as possible.
I need to call certain PHP callbacks while passing integers as parameters. I've been thinking of somehow using code from the php pthreads extension (github.com/krakjoe/pthreads), but I still haven't figured out how does it manage threads.
@Danogentili But you don't need to create any threads to invoke php callbacks. You simply export some kind of pull function and invoke php callbacks when control reaches it inside of php code.
The threads are created by the libtgvoip library, and user-defined c++ callbacks will be called from these threads. I'm trying to make these c++ callbacks call PHP callbacks.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.