feat(extension): 添加请求生命周期钩子函数支持

- 在扩展模板中添加 PHP_RINIT 和 PHP_RSHUTDOWN 函数实现
- 配置模块入口结构以启用请求初始化和关闭回调
- 更新主程序初始化逻辑以使用模块生命周期函数
- 实现请求启动和关闭时的应用程序初始化清理功能
- 解决 PHP 内部字符串处理的双释放问题
- 简化示例代码以演示全局变量访问功能
pull/1/head
韩天峰 7 months ago
parent 38110f67d5
commit 6632629f58
  1. 39
      examples/hello.php
  2. 52
      src/cpp/main.cc
  3. 16
      src/template/extension.cc.php

@ -1,33 +1,14 @@
<?php <?php
function main(int $argc, array $argv): int function main(): int
{ {
$a = 1; global $a;
$b = 2; $a = 100;
$c = 3.12343;
$d = 'hello'; var_dump($GLOBALS['a']);
$e = ['hello' => 1, 'world' => 33.43]; var_dump($a);
var_dump(gettype($_SERVER));
for ($i = 1; $i < $argc; ++$i) { var_dump($_SERVER['argc']);
$a += $argv[$i]; var_dump($_SERVER['argv']);
} return 0;
$argc = 999;
$a = $b * 13;
$a += $b << 4;
$a += $b >> 1;
$_tmp = $e['hello'];
$_tmp -= 4;
$_tmp *= 5;
$_tmp /= 10;
$_tmp %= 10;
var_dump($_tmp, 1000);
echo "value:=" . ($a + $b);
echo "value:=", $a, $b;
return $a * $b;
} }

@ -4,35 +4,44 @@
#endif #endif
#include <phpx.h> #include <phpx.h>
extern php::Var argc;
extern php::Var argv;
extern void php_app_init();
extern void php_app_clean();
extern zend_module_entry *php_embed_get_module(); extern zend_module_entry *php_embed_get_module();
int main(int cpp_argc, char **cpp_argv) { void module_init(zend_module_entry *module) {
php_embed_init(cpp_argc, cpp_argv);
php::throw_impl = [](zend_object *ex) { throw ex; };
zend_module_entry *module = php_embed_get_module();
if (zend_register_module_ex(module, MODULE_PERSISTENT) == NULL) { if (zend_register_module_ex(module, MODULE_PERSISTENT) == NULL) {
zend_error(E_ERROR, "Failed to register module [%s]", module->name); zend_error(E_ERROR, "Failed to register module [%s]", module->name);
return 255; exit(255);
} }
if (zend_startup_module_ex(module) == FAILURE) { if (zend_startup_module_ex(module) == FAILURE) {
zend_error(E_ERROR, "Failed to startup module [%s]", module->name); zend_error(E_ERROR, "Failed to startup module [%s]", module->name);
return 255; exit(255);
} }
}
void module_shutdown(zend_module_entry *module) {
/**
* There is a bug in PHP's handling of internal strings. All interned strings are released in the request shutdown
* function, but then released again in the php_embed_shutdown function, resulting in a use-after-free issue. These
* must be manually removed from the module table to prevent double release.
*/
auto name_len = strlen(module->name);
auto lcname = zend_string_alloc(name_len, module->type == MODULE_PERSISTENT);
zend_str_tolower_copy(ZSTR_VAL(lcname), module->name, name_len);
zend_hash_del(&module_registry, lcname);
}
int main(int cpp_argc, char **cpp_argv) {
php_embed_init(cpp_argc, cpp_argv);
php::throw_impl = [](zend_object *ex) { throw ex; };
zend_module_entry *module = php_embed_get_module();
module_init(module);
int rc = 0; int rc = 0;
#if PPROF_ON #if PPROF_ON
ProfilerStart("profile.out"); ProfilerStart("profile.out");
#endif #endif
try { try {
php::request_init(); module->request_startup_func(module->type, module->module_number);
php_app_init();
php::eval("main();"); php::eval("main();");
} catch (zend_object *e) { } catch (zend_object *e) {
rc = EG(exit_status); rc = EG(exit_status);
@ -41,19 +50,8 @@ int main(int cpp_argc, char **cpp_argv) {
#if PPROF_ON #if PPROF_ON
ProfilerStop(); ProfilerStop();
#endif #endif
php_app_clean();
php::request_shutdown();
/**
* There is a bug in PHP's handling of internal strings. All interned strings are released in the request shutdown
* function, but then released again in the php_embed_shutdown function, resulting in a use-after-free issue. These
* must be manually removed from the module table to prevent double release.
*/
auto name_len = strlen(module->name);
auto lcname = zend_string_alloc(name_len, module->type == MODULE_PERSISTENT);
zend_str_tolower_copy(ZSTR_VAL(lcname), module->name, name_len);
zend_hash_del(&module_registry, lcname);
module->request_shutdown_func(module->type, module->module_number);
php_embed_shutdown(); php_embed_shutdown();
return rc; return rc;

@ -136,14 +136,26 @@ foreach ($this->nativeConstants as $name => $constant):
<?php endforeach; ?> <?php endforeach; ?>
} }
static PHP_RINIT_FUNCTION(<?=$this->targetName?>) {
php::request_init();
php_app_init();
return SUCCESS;
}
static PHP_RSHUTDOWN_FUNCTION(<?=$this->targetName?>) {
php_app_clean();
php::request_shutdown();
return SUCCESS;
}
zend_module_entry <?=$this->targetName?>_module_entry = { zend_module_entry <?=$this->targetName?>_module_entry = {
STANDARD_MODULE_HEADER, STANDARD_MODULE_HEADER,
"<?=$this->targetName?>", "<?=$this->targetName?>",
ext_functions, ext_functions,
PHP_MINIT(<?=$this->targetName?>), PHP_MINIT(<?=$this->targetName?>),
nullptr, nullptr,
nullptr, PHP_RINIT(<?=$this->targetName?>),
nullptr, PHP_RSHUTDOWN(<?=$this->targetName?>),
nullptr, nullptr,
nullptr, nullptr,
STANDARD_MODULE_PROPERTIES, STANDARD_MODULE_PROPERTIES,

Loading…
Cancel
Save