Skip to content

Commit ddb78c5

Browse files
committed
Refactor register shutdown function mechanism
Note: Some tests seem to hang
1 parent 05e6f3e commit ddb78c5

File tree

5 files changed

+50
-44
lines changed

5 files changed

+50
-44
lines changed

Zend/tests/bug41026.phpt

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ class try_class
1212

1313
static public function on_shutdown ()
1414
{
15-
printf ("CHECKPOINT\n"); /* never reached */
15+
printf ("CHECKPOINT\n");
1616
}
1717
}
1818

@@ -22,5 +22,4 @@ echo "Done\n";
2222
?>
2323
--EXPECT--
2424
Done
25-
26-
Fatal error: Registered shutdown function self::on_shutdown() cannot be called, function does not exist in Unknown on line 0
25+
CHECKPOINT

ext/session/session.c

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2047,13 +2047,18 @@ PHP_FUNCTION(session_set_save_handler)
20472047
if (register_shutdown) {
20482048
/* create shutdown function */
20492049
php_shutdown_function_entry shutdown_function_entry;
2050-
ZVAL_STRING(&shutdown_function_entry.function_name, "session_register_shutdown");
2051-
shutdown_function_entry.arg_count = 0;
2052-
shutdown_function_entry.arguments = NULL;
2050+
zval callable;
2051+
zend_result result;
2052+
2053+
ZVAL_STRING(&callable, "session_register_shutdown");
2054+
result = zend_fcall_info_init(&callable, 0, &shutdown_function_entry.fci,
2055+
&shutdown_function_entry.fci_cache, NULL, NULL);
2056+
2057+
ZEND_ASSERT(result == SUCCESS);
20532058

20542059
/* add shutdown function, removing the old one if it exists */
20552060
if (!register_user_shutdown_function("session_shutdown", sizeof("session_shutdown") - 1, &shutdown_function_entry)) {
2056-
zval_ptr_dtor(&shutdown_function_entry.function_name);
2061+
//zval_ptr_dtor(&shutdown_function_entry.function_name);
20572062
php_error_docref(NULL, E_WARNING, "Unable to register session shutdown function");
20582063
RETURN_FALSE;
20592064
}
@@ -2654,6 +2659,8 @@ PHP_FUNCTION(session_status)
26542659
PHP_FUNCTION(session_register_shutdown)
26552660
{
26562661
php_shutdown_function_entry shutdown_function_entry;
2662+
zval callable;
2663+
zend_result result;
26572664

26582665
ZEND_PARSE_PARAMETERS_NONE();
26592666

@@ -2663,13 +2670,15 @@ PHP_FUNCTION(session_register_shutdown)
26632670
* function after calling session_set_save_handler(), which expects
26642671
* the session still to be available.
26652672
*/
2673+
ZVAL_STRING(&callable, "session_write_close");
2674+
result = zend_fcall_info_init(&callable, 0, &shutdown_function_entry.fci,
2675+
&shutdown_function_entry.fci_cache, NULL, NULL);
26662676

2667-
ZVAL_STRING(&shutdown_function_entry.function_name, "session_write_close");
2668-
shutdown_function_entry.arg_count = 0;
2669-
shutdown_function_entry.arguments = NULL;
2677+
ZEND_ASSERT(result == SUCCESS);
26702678

26712679
if (!append_user_shutdown_function(&shutdown_function_entry)) {
2672-
zval_ptr_dtor(&shutdown_function_entry.function_name);
2680+
zval_ptr_dtor(&shutdown_function_entry.fci.function_name);
2681+
//efree(shutdown_function_entry);
26732682

26742683
/* Unable to register shutdown function, presumably because of lack
26752684
* of memory, so flush the session now. It would be done in rshutdown

ext/standard/basic_functions.c

Lines changed: 28 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1664,14 +1664,13 @@ PHP_FUNCTION(forward_static_call_array)
16641664

16651665
void user_shutdown_function_dtor(zval *zv) /* {{{ */
16661666
{
1667-
int i;
16681667
php_shutdown_function_entry *shutdown_function_entry = Z_PTR_P(zv);
16691668

1670-
zval_ptr_dtor(&shutdown_function_entry->function_name);
1671-
for (i = 0; i < shutdown_function_entry->arg_count; i++) {
1672-
zval_ptr_dtor(&shutdown_function_entry->arguments[i]);
1669+
zval_ptr_dtor(&shutdown_function_entry->fci.function_name);
1670+
for (size_t i = 0; i < shutdown_function_entry->fci.param_count; i++) {
1671+
zval_ptr_dtor(&shutdown_function_entry->fci.params[i]);
16731672
}
1674-
efree(shutdown_function_entry->arguments);
1673+
16751674
efree(shutdown_function_entry);
16761675
}
16771676
/* }}} */
@@ -1689,24 +1688,24 @@ void user_tick_function_dtor(user_tick_function_entry *tick_function_entry) /* {
16891688

16901689
static int user_shutdown_function_call(zval *zv) /* {{{ */
16911690
{
1692-
php_shutdown_function_entry *shutdown_function_entry = Z_PTR_P(zv);
1693-
zval retval;
1691+
php_shutdown_function_entry *shutdown_function_entry = Z_PTR_P(zv);
1692+
zval tmp;
1693+
zend_result call_status;
16941694

1695-
if (!zend_is_callable(&shutdown_function_entry->function_name, 0, NULL)) {
1696-
zend_string *function_name = zend_get_callable_name(&shutdown_function_entry->function_name);
1695+
if (!zend_is_callable(&shutdown_function_entry->fci.function_name, 0, NULL)) {
1696+
zend_string *function_name = zend_get_callable_name(&shutdown_function_entry->fci.function_name);
16971697
zend_throw_error(NULL, "Registered shutdown function %s() cannot be called, function does not exist", ZSTR_VAL(function_name));
16981698
zend_string_release(function_name);
16991699
return 0;
17001700
}
17011701

1702-
if (call_user_function(NULL, NULL,
1703-
&shutdown_function_entry->function_name,
1704-
&retval,
1705-
shutdown_function_entry->arg_count,
1706-
shutdown_function_entry->arguments) == SUCCESS)
1707-
{
1708-
zval_ptr_dtor(&retval);
1709-
}
1702+
/* set tmp zval */
1703+
shutdown_function_entry->fci.retval = &tmp;
1704+
call_status = zend_call_function(&shutdown_function_entry->fci, &shutdown_function_entry->fci_cache);
1705+
ZEND_ASSERT(call_status == SUCCESS);
1706+
1707+
/* Destroy return value */
1708+
zval_ptr_dtor(&tmp);
17101709
return 0;
17111710
}
17121711
/* }}} */
@@ -1789,24 +1788,24 @@ PHPAPI void php_free_shutdown_functions(void) /* {{{ */
17891788
/* {{{ Register a user-level function to be called on request termination */
17901789
PHP_FUNCTION(register_shutdown_function)
17911790
{
1792-
php_shutdown_function_entry entry;
1793-
zend_fcall_info fci;
1794-
zend_fcall_info_cache fcc;
1795-
zval *args;
1796-
int arg_count = 0;
1791+
php_shutdown_function_entry *entry = emalloc(sizeof(php_shutdown_function_entry));
1792+
bool status = false;
17971793

1798-
if (zend_parse_parameters(ZEND_NUM_ARGS(), "f*", &fci, &fcc, &args, &arg_count) == FAILURE) {
1794+
if (zend_parse_parameters(ZEND_NUM_ARGS(), "f*", &entry->fci, &entry->fci_cache,
1795+
&entry->fci.params, &entry->fci.param_count) == FAILURE) {
1796+
efree(entry);
17991797
RETURN_THROWS();
18001798
}
18011799

1802-
ZVAL_COPY(&entry.function_name, &fci.function_name);
1803-
entry.arguments = (zval *) safe_emalloc(sizeof(zval), arg_count, 0);
1804-
entry.arg_count = arg_count;
1805-
for (int i = 0; i < arg_count; i++) {
1806-
ZVAL_COPY(&entry.arguments[i], &args[i]);
1800+
Z_TRY_ADDREF(entry->fci.function_name);
1801+
for (size_t i = 0; i < entry->fci.param_count; i++) {
1802+
Z_TRY_ADDREF(entry->fci.params[i]);
18071803
}
18081804

1809-
append_user_shutdown_function(&entry);
1805+
status = append_user_shutdown_function(entry);
1806+
ZEND_ASSERT(status);
1807+
1808+
efree(entry);
18101809
}
18111810
/* }}} */
18121811

ext/standard/basic_functions.h

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -143,9 +143,8 @@ PHPAPI double php_get_nan(void);
143143
PHPAPI double php_get_inf(void);
144144

145145
typedef struct _php_shutdown_function_entry {
146-
zval function_name;
147-
zval *arguments;
148-
int arg_count;
146+
zend_fcall_info fci;
147+
zend_fcall_info_cache fci_cache;
149148
} php_shutdown_function_entry;
150149

151150
PHPAPI extern bool register_user_shutdown_function(const char *function_name, size_t function_len, php_shutdown_function_entry *shutdown_function_entry);

ext/standard/tests/general_functions/010.phpt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ class test {
1212
}
1313

1414
try {
15-
register_shutdown_function(array("test","__call"));
15+
var_dump(register_shutdown_function(array("test","__call")));
1616
} catch (TypeError $exception) {
1717
echo $exception->getMessage() . "\n";
1818
}

0 commit comments

Comments
 (0)