Skip to content

Commit

Permalink
Fix exit hook for php 8.4
Browse files Browse the repository at this point in the history
  • Loading branch information
dixyes committed Nov 26, 2024
1 parent 9bb2efd commit f578566
Show file tree
Hide file tree
Showing 3 changed files with 95 additions and 0 deletions.
35 changes: 35 additions & 0 deletions ext/src/swow_coroutine.c
Original file line number Diff line number Diff line change
Expand Up @@ -2509,6 +2509,36 @@ static int swow_coroutine_exit_handler(zend_execute_data *execute_data)

return ZEND_USER_OPCODE_CONTINUE;
}
#else
// from php/php-src@bc07a8a28a084a9bd2637b8232b75d1634a5872e Zend/zend_builtin_functions.c L72
static PHP_FUNCTION(swow_exit)
{
swow_coroutine_t *s_coroutine = swow_coroutine_get_current();
zend_string *str = NULL;
zend_long status = 0;

ZEND_PARSE_PARAMETERS_START(0, 1)
Z_PARAM_OPTIONAL
Z_PARAM_STR_OR_LONG(str, status)
ZEND_PARSE_PARAMETERS_END();

if (str) {
size_t len = ZSTR_LEN(str);
if (len != 0) {
/* An exception might be emitted by an output handler */
zend_write(ZSTR_VAL(str), len);
if (EG(exception)) {
RETURN_THROWS();
}
}
} else {
EG(exit_status) = status;
s_coroutine->exit_status = status;
}

ZEND_ASSERT(!EG(exception));
zend_throw_unwind_exit();
}
#endif // ZEND_EXIT

/* hook silence */
Expand Down Expand Up @@ -2681,6 +2711,11 @@ zend_result swow_coroutine_module_init(INIT_FUNC_ARGS)
# ifdef ZEND_EXIT
/* hook opcode exit */
zend_set_user_opcode_handler(ZEND_EXIT, swow_coroutine_exit_handler);
# else
/* hook function exit */
if (!swow_hook_internal_function_handler(CAT_STRL("exit"), PHP_FN(swow_exit))) {
return FAILURE;
}
# endif // ZEND_EXIT
# ifdef SWOW_COROUTINE_SWAP_SILENCE_CONTEXT
/* hook opcode silence */
Expand Down
1 change: 1 addition & 0 deletions ext/tests/swow_coroutine/exit.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ swow_coroutine: exit
--SKIPIF--
<?php
require __DIR__ . '/../include/skipif.php';
needs_php_version('<', '8.4');
?>
--FILE--
<?php
Expand Down
59 changes: 59 additions & 0 deletions ext/tests/swow_coroutine/exit_84.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
--TEST--
swow_coroutine: exit
--SKIPIF--
<?php
require __DIR__ . '/../include/skipif.php';
needs_php_version('>=', '8.4');
?>
--FILE--
<?php
require __DIR__ . '/../include/bootstrap.php';

$coroutine = Swow\Coroutine::run(static function (): void {
echo "0\n";
exit;
/* @noinspection PhpUnreachableStatementInspection */
echo "Never here\n";
});
Assert::same($coroutine->getExitStatus(), 0);

$coroutine = Swow\Coroutine::run(static function (): void {
echo "1\n";
exit(0);
/* @noinspection PhpUnreachableStatementInspection */
echo "Never here\n";
});
Assert::same($coroutine->getExitStatus(), 0);

$coroutine = Swow\Coroutine::run(static function (): void {
echo "2\n";
exit(null);
/* @noinspection PhpUnreachableStatementInspection */
echo "Never here\n";
});
Assert::same($coroutine->getExitStatus(), 0);

$coroutine = Swow\Coroutine::run(static function (): void {
echo "3\n";
exit(1);
/* @noinspection PhpUnreachableStatementInspection */
echo "Never here\n";
});
Assert::same($coroutine->getExitStatus(), 1);

echo "Done\n";

?>
--EXPECTF--
0
1
2
%Aeprecated: [Deprecated in R%d] exit(): Passing null to parameter #1 ($status) of type string|int is deprecated
Stack trace:
#0 %sexit_84.php(%d): exit(NULL)
#1 [internal function]: {closure:%sexit_84.php:%d}()
#2 %sexit_84.php(%d): Swow\Coroutine::run(Object(Closure))
#3 {main}
triggered in %sexit_84.php on line %d
3
Done

0 comments on commit f578566

Please sign in to comment.