Skip to content

Commit 433d47d

Browse files
committed
sapi: only use FCC for header_register_callback()
No need to rederive callability of zval, or copies of it
1 parent 1f4a88c commit 433d47d

3 files changed

Lines changed: 31 additions & 41 deletions

File tree

main/SAPI.c

Lines changed: 14 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -111,51 +111,26 @@ PHP_FUNCTION(header_register_callback)
111111
zend_fcall_info fci;
112112
zend_fcall_info_cache fcc;
113113

114-
if (zend_parse_parameters(ZEND_NUM_ARGS(), "f", &fci, &fcc) == FAILURE) {
114+
if (zend_parse_parameters(ZEND_NUM_ARGS(), "F", &fci, &fcc) == FAILURE) {
115115
RETURN_THROWS();
116116
}
117117

118-
if (Z_TYPE(SG(callback_func)) != IS_UNDEF) {
119-
zval_ptr_dtor(&SG(callback_func));
120-
SG(fci_cache) = empty_fcall_info_cache;
118+
if (ZEND_FCC_INITIALIZED(SG(send_header_fcc))) {
119+
zend_fcc_dtor(&SG(send_header_fcc));
120+
SG(send_header_fcc) = empty_fcall_info_cache;
121121
}
122122

123123
/* Don't store callback if headers have already been sent:
124124
* It won't get used and we won't have a chance to release it. */
125-
if (!SG(headers_sent)) {
126-
ZVAL_COPY(&SG(callback_func), &fci.function_name);
125+
if (UNEXPECTED(SG(headers_sent))) {
126+
zend_release_fcall_info_cache(&fcc);
127127
}
128128

129+
zend_fcc_dup(&SG(send_header_fcc), &fcc);
129130
RETURN_TRUE;
130131
}
131132
/* }}} */
132133

133-
static void sapi_run_header_callback(zval *callback)
134-
{
135-
int error;
136-
zend_fcall_info fci;
137-
char *callback_error = NULL;
138-
zval retval;
139-
140-
if (zend_fcall_info_init(callback, 0, &fci, &SG(fci_cache), NULL, &callback_error) == SUCCESS) {
141-
fci.retval = &retval;
142-
143-
error = zend_call_function(&fci, &SG(fci_cache));
144-
if (error == FAILURE) {
145-
goto callback_failed;
146-
} else {
147-
zval_ptr_dtor(&retval);
148-
}
149-
} else {
150-
callback_failed:
151-
php_error_docref(NULL, E_WARNING, "Could not call the sapi_header_callback");
152-
}
153-
154-
if (callback_error) {
155-
efree(callback_error);
156-
}
157-
}
158-
159134
SAPI_API void sapi_handle_post(void *arg)
160135
{
161136
if (SG(request_info).post_entry && SG(request_info).content_type_dup) {
@@ -436,7 +411,6 @@ SAPI_API void sapi_activate(void)
436411
SG(sapi_headers).http_status_line = NULL;
437412
SG(sapi_headers).mimetype = NULL;
438413
SG(headers_sent) = 0;
439-
ZVAL_UNDEF(&SG(callback_func));
440414
SG(read_post_bytes) = 0;
441415
SG(request_info).request_body = NULL;
442416
SG(request_info).current_user = NULL;
@@ -446,6 +420,7 @@ SAPI_API void sapi_activate(void)
446420
SG(request_info).proto_num = 1000; /* Default to HTTP 1.0 */
447421
SG(global_request_time) = 0;
448422
SG(post_read) = 0;
423+
SG(send_header_fcc) = empty_fcall_info_cache;
449424
/* It's possible to override this general case in the activate() callback, if necessary. */
450425
if (SG(request_info).request_method && !strcmp(SG(request_info).request_method, "HEAD")) {
451426
SG(request_info).headers_only = 1;
@@ -890,12 +865,12 @@ SAPI_API int sapi_send_headers(void)
890865
SG(sapi_headers).send_default_content_type = 0;
891866
}
892867

893-
if (Z_TYPE(SG(callback_func)) != IS_UNDEF) {
894-
zval cb;
895-
ZVAL_COPY_VALUE(&cb, &SG(callback_func));
896-
ZVAL_UNDEF(&SG(callback_func));
897-
sapi_run_header_callback(&cb);
898-
zval_ptr_dtor(&cb);
868+
if (ZEND_FCC_INITIALIZED(SG(send_header_fcc))) {
869+
zend_fcall_info_cache fcc = SG(send_header_fcc);
870+
/* Prevent triggering the callback multiple times */
871+
SG(send_header_fcc) = empty_fcall_info_cache;
872+
zend_call_known_fcc(&fcc, NULL, 0, NULL, NULL);
873+
zend_fcc_dtor(&fcc);
899874
}
900875

901876
SG(headers_sent) = 1;

main/SAPI.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -143,8 +143,7 @@ typedef struct _sapi_globals_struct {
143143
bool sapi_started;
144144
double global_request_time;
145145
HashTable known_post_content_types;
146-
zval callback_func;
147-
zend_fcall_info_cache fci_cache;
146+
zend_fcall_info_cache send_header_fcc;
148147
sapi_request_parse_body_context request_parse_body_context;
149148
} sapi_globals_struct;
150149

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
--TEST--
2+
Test header_register_callback
3+
--FILE--
4+
<?php
5+
class TrampolineTest {
6+
public function __call(string $name, array $arguments) {
7+
echo 'Trampoline for ', $name, PHP_EOL;
8+
}
9+
}
10+
$o = new TrampolineTest();
11+
$callback = [$o, 'trampoline'];
12+
13+
header_register_callback($callback);
14+
?>
15+
--EXPECT--
16+
Trampoline for trampoline

0 commit comments

Comments
 (0)