1

我目前正在开发一个 PHP 扩展。这个 PHP 扩展还应该通过 pthreads 使用多线程。在线程内部,PHP 用户空间中的一个函数应该通过call_user_function. PHP 使用--enable-maintainer-ztsconfig 选项进行配置。

我已经编写了一些在用户空间中调用 PHP 函数的代码,它按预期工作。请参阅以下代码片段以获取最小的工作示例:

扩展代码(在 C 中)

PHP_FUNCTION(hello_world)
{
    startWorker();
    RETURN_NULL();
}

void *startWorker() {

    static zval retval;

    zval function_name;
    INIT_ZVAL(function_name);
    ZVAL_STRING(&function_name, "hello", 1);

    TSRMLS_FETCH();

    if (call_user_function(CG(function_table), NULL, &function_name, &retval, 0, NULL TSRMLS_CC) == SUCCESS) {
        printf("successfully called function\n");
    } else {
        printf("calling user function returned an error\n");
    }

    zval_dtor(&function_name);
}

PHP代码:

<?php

function hello() {
        echo "php hello() called\n";
}
hello_world();

如果我调用 PHP 代码,它会返回以下输出 - 正如预期的那样。

php hello() called
successfully called function

但现在我想从一个新线程调用 PHP 函数。所以我修改扩展代码如下:

PHP_FUNCTION(hello_world)
{
    pthread_t thread;
    pthread_create( &thread, NULL, &startWorker, NULL);
    pthread_join(thread, NULL);
    RETURN_NULL();
}

但是现在,突然之间,调用 PHP 代码会导致以下输出:

calling user function returned an error

我可以将错误的来源追溯到 zend_call_function中的以下 if 语句,但是我不知道为什么EG(active)此时为 false 以及如何防止这种情况发生:

if (!EG(active)) {
    return FAILURE; /* executor is already inactive */
}

所以我的问题是:

  • 甚至可以在线程内调用 PHP 用户空间函数吗?
  • 如果是这样,为什么会call_user_function返回错误?
  • EG(主动)是什么意思?如何让它在 pthread 中评估为 true?

对此的任何提示都将受到高度赞赏。

4

0 回答 0