Skip to content

Commit 9fe35ba

Browse files
committed
Refactor register_tick_function mechanism
1 parent af1de14 commit 9fe35ba

File tree

4 files changed

+27
-84
lines changed

4 files changed

+27
-84
lines changed

ext/standard/basic_functions.c

Lines changed: 23 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -111,9 +111,9 @@ PHPAPI php_basic_globals basic_globals;
111111
static zend_class_entry *incomplete_class_entry = NULL;
112112

113113
typedef struct _user_tick_function_entry {
114-
zval *arguments;
115-
int arg_count;
116-
int calling;
114+
zend_fcall_info fci;
115+
zend_fcall_info_cache fci_cache;
116+
bool calling;
117117
} user_tick_function_entry;
118118

119119
/* some prototypes for local functions */
@@ -1673,12 +1673,9 @@ void user_shutdown_function_dtor(zval *zv) /* {{{ */
16731673

16741674
void user_tick_function_dtor(user_tick_function_entry *tick_function_entry) /* {{{ */
16751675
{
1676-
int i;
1676+
zval_ptr_dtor(&tick_function_entry->fci.function_name);
16771677

1678-
for (i = 0; i < tick_function_entry->arg_count; i++) {
1679-
zval_ptr_dtor(&tick_function_entry->arguments[i]);
1680-
}
1681-
efree(tick_function_entry->arguments);
1678+
efree(tick_function_entry);
16821679
}
16831680
/* }}} */
16841681

@@ -1709,38 +1706,18 @@ static int user_shutdown_function_call(zval *zv) /* {{{ */
17091706

17101707
static void user_tick_function_call(user_tick_function_entry *tick_fe) /* {{{ */
17111708
{
1712-
zval retval;
1713-
zval *function = &tick_fe->arguments[0];
1714-
1715-
/* Prevent reentrant calls to the same user ticks function */
1716-
if (! tick_fe->calling) {
1717-
tick_fe->calling = 1;
1709+
/* Prevent re-entrant calls to the same user ticks function */
1710+
if (!tick_fe->calling) {
1711+
zval retval;
1712+
tick_fe->calling = true;
17181713

1719-
if (call_user_function(NULL, NULL,
1720-
function,
1721-
&retval,
1722-
tick_fe->arg_count - 1,
1723-
tick_fe->arguments + 1
1724-
) == SUCCESS) {
1725-
zval_ptr_dtor(&retval);
1726-
1727-
} else {
1728-
zval *obj, *method;
1729-
1730-
if (Z_TYPE_P(function) == IS_STRING) {
1731-
php_error_docref(NULL, E_WARNING, "Unable to call %s() - function does not exist", Z_STRVAL_P(function));
1732-
} else if ( Z_TYPE_P(function) == IS_ARRAY
1733-
&& (obj = zend_hash_index_find(Z_ARRVAL_P(function), 0)) != NULL
1734-
&& (method = zend_hash_index_find(Z_ARRVAL_P(function), 1)) != NULL
1735-
&& Z_TYPE_P(obj) == IS_OBJECT
1736-
&& Z_TYPE_P(method) == IS_STRING) {
1737-
php_error_docref(NULL, E_WARNING, "Unable to call %s::%s() - function does not exist", ZSTR_VAL(Z_OBJCE_P(obj)->name), Z_STRVAL_P(method));
1738-
} else {
1739-
php_error_docref(NULL, E_WARNING, "Unable to call tick function");
1740-
}
1714+
tick_fe->fci.retval = &retval;
1715+
if (zend_call_function(&tick_fe->fci, &tick_fe->fci_cache) == SUCCESS) {
1716+
zval_ptr_dtor(tick_fe->fci.retval);
17411717
}
17421718

1743-
tick_fe->calling = 0;
1719+
zend_release_fcall_info_cache(&tick_fe->fci_cache);
1720+
tick_fe->calling = false;
17441721
}
17451722
}
17461723
/* }}} */
@@ -1753,8 +1730,8 @@ static void run_user_tick_functions(int tick_count, void *arg) /* {{{ */
17531730

17541731
static int user_tick_function_compare(user_tick_function_entry * tick_fe1, user_tick_function_entry * tick_fe2) /* {{{ */
17551732
{
1756-
zval *func1 = &tick_fe1->arguments[0];
1757-
zval *func2 = &tick_fe2->arguments[0];
1733+
zval *func1 = &tick_fe1->fci.function_name;
1734+
zval *func2 = &tick_fe2->fci.function_name;
17581735
int ret;
17591736

17601737
if (Z_TYPE_P(func1) == IS_STRING && Z_TYPE_P(func2) == IS_STRING) {
@@ -2408,35 +2385,13 @@ PHP_FUNCTION(getprotobynumber)
24082385
PHP_FUNCTION(register_tick_function)
24092386
{
24102387
user_tick_function_entry tick_fe;
2411-
int i;
2412-
zend_string *function_name = NULL;
2413-
2414-
tick_fe.calling = 0;
2415-
tick_fe.arg_count = ZEND_NUM_ARGS();
2416-
2417-
if (tick_fe.arg_count < 1) {
2418-
WRONG_PARAM_COUNT;
2419-
}
24202388

2421-
tick_fe.arguments = (zval *) safe_emalloc(sizeof(zval), tick_fe.arg_count, 0);
2422-
2423-
if (zend_get_parameters_array(ZEND_NUM_ARGS(), tick_fe.arg_count, tick_fe.arguments) == FAILURE) {
2424-
efree(tick_fe.arguments);
2425-
RETURN_FALSE;
2426-
}
2427-
2428-
if (!zend_is_callable(&tick_fe.arguments[0], 0, &function_name)) {
2429-
efree(tick_fe.arguments);
2430-
zend_argument_type_error(1, "must be a valid tick callback, '%s' given", ZSTR_VAL(function_name));
2431-
zend_string_release_ex(function_name, 0);
2432-
RETURN_THROWS();
2433-
} else if (function_name) {
2434-
zend_string_release_ex(function_name, 0);
2435-
}
2389+
ZEND_PARSE_PARAMETERS_START(1, -1)
2390+
Z_PARAM_FUNC(tick_fe.fci, tick_fe.fci_cache)
2391+
Z_PARAM_VARIADIC('*', tick_fe.fci.params, tick_fe.fci.param_count)
2392+
ZEND_PARSE_PARAMETERS_END();
24362393

2437-
if (Z_TYPE(tick_fe.arguments[0]) != IS_ARRAY && Z_TYPE(tick_fe.arguments[0]) != IS_OBJECT) {
2438-
convert_to_string_ex(&tick_fe.arguments[0]);
2439-
}
2394+
Z_TRY_ADDREF(tick_fe.fci.function_name);
24402395

24412396
if (!BG(user_tick_functions)) {
24422397
BG(user_tick_functions) = (zend_llist *) emalloc(sizeof(zend_llist));
@@ -2446,10 +2401,6 @@ PHP_FUNCTION(register_tick_function)
24462401
php_add_tick_function(run_user_tick_functions, NULL);
24472402
}
24482403

2449-
for (i = 0; i < tick_fe.arg_count; i++) {
2450-
Z_TRY_ADDREF(tick_fe.arguments[i]);
2451-
}
2452-
24532404
zend_llist_add_element(BG(user_tick_functions), &tick_fe);
24542405

24552406
RETURN_TRUE;
@@ -2459,26 +2410,18 @@ PHP_FUNCTION(register_tick_function)
24592410
/* {{{ Unregisters a tick callback function */
24602411
PHP_FUNCTION(unregister_tick_function)
24612412
{
2462-
zval *function;
24632413
user_tick_function_entry tick_fe;
24642414

24652415
ZEND_PARSE_PARAMETERS_START(1, 1)
2466-
Z_PARAM_ZVAL(function)
2416+
Z_PARAM_FUNC(tick_fe.fci, tick_fe.fci_cache)
24672417
ZEND_PARSE_PARAMETERS_END();
24682418

24692419
if (!BG(user_tick_functions)) {
24702420
return;
24712421
}
24722422

2473-
if (Z_TYPE_P(function) != IS_ARRAY && Z_TYPE_P(function) != IS_OBJECT) {
2474-
convert_to_string(function);
2475-
}
2476-
2477-
tick_fe.arguments = (zval *) emalloc(sizeof(zval));
2478-
ZVAL_COPY_VALUE(&tick_fe.arguments[0], function);
2479-
tick_fe.arg_count = 1;
24802423
zend_llist_del_element(BG(user_tick_functions), &tick_fe, (int (*)(void *, void *)) user_tick_function_compare);
2481-
efree(tick_fe.arguments);
2424+
//efree(tick_fe.arguments);
24822425
}
24832426
/* }}} */
24842427

ext/standard/basic_functions.stub.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -346,7 +346,7 @@ function getprotobynumber(int $protocol): string|false {}
346346

347347
function register_tick_function(callable $function, mixed ...$args): bool {}
348348

349-
function unregister_tick_function($function): void {}
349+
function unregister_tick_function(callable $function): void {}
350350

351351
function is_uploaded_file(string $path): bool {}
352352

ext/standard/basic_functions_arginfo.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/* This is a generated file, edit the .stub.php file instead.
2-
* Stub hash: 05b740207a70a9d272b4c327882fd0b52016a0af */
2+
* Stub hash: 70d5985247cf278a39dd8415109214fda882f101 */
33

44
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_set_time_limit, 0, 1, _IS_BOOL, 0)
55
ZEND_ARG_TYPE_INFO(0, seconds, IS_LONG, 0)
@@ -554,7 +554,7 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_register_tick_function, 0, 1, _I
554554
ZEND_END_ARG_INFO()
555555

556556
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_unregister_tick_function, 0, 1, IS_VOID, 0)
557-
ZEND_ARG_INFO(0, function)
557+
ZEND_ARG_TYPE_INFO(0, function, IS_CALLABLE, 0)
558558
ZEND_END_ARG_INFO()
559559

560560
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_is_uploaded_file, 0, 1, _IS_BOOL, 0)

ext/standard/tests/general_functions/register_tick_function_error.phpt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,4 +11,4 @@ try {
1111
}
1212
?>
1313
--EXPECT--
14-
register_tick_function(): Argument #1 ($function) must be a valid tick callback, 'a' given
14+
register_tick_function(): Argument #1 ($function) must be a valid callback, function 'a' not found or invalid function name

0 commit comments

Comments
 (0)