Skip to content

Commit 3704b98

Browse files
henderkesdunglas
andauthored
fix ext-parallel crashes (#2438)
ext-parallel threads now use their parents thread_index when reaching into the go runtime, fixes #2339 --------- Signed-off-by: Marc <m@pyc.ac> Co-authored-by: Kévin Dunglas <kevin@dunglas.fr>
1 parent 7e1a133 commit 3704b98

1 file changed

Lines changed: 32 additions & 14 deletions

File tree

frankenphp.c

Lines changed: 32 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,21 @@ __thread uintptr_t thread_index;
9393
__thread bool is_worker_thread = false;
9494
__thread HashTable *sandboxed_env = NULL;
9595

96+
/* Published via SG(server_context) so ext-parallel children, which inherit
97+
* the parent's SG(server_context), can route SAPI callbacks back to the
98+
* parent's thread_index instead of their zero-initialized TLS. */
99+
typedef struct {
100+
uintptr_t thread_index;
101+
} frankenphp_server_ctx;
102+
static __thread frankenphp_server_ctx frankenphp_local_server_ctx;
103+
104+
static inline uintptr_t frankenphp_thread_index(void) {
105+
frankenphp_server_ctx *ctx = (frankenphp_server_ctx *)SG(server_context);
106+
/* Fall back to the OS thread's own TLS before
107+
* frankenphp_update_request_context(). */
108+
return ctx == NULL ? thread_index : ctx->thread_index;
109+
}
110+
96111
#ifndef PHP_WIN32
97112
static bool is_forked_child = false;
98113
static void frankenphp_fork_child(void) { is_forked_child = true; }
@@ -217,7 +232,8 @@ void frankenphp_update_local_thread_context(bool is_worker) {
217232
static void frankenphp_update_request_context() {
218233
/* the server context is stored on the go side, still SG(server_context) needs
219234
* to not be NULL */
220-
SG(server_context) = (void *)1;
235+
frankenphp_local_server_ctx.thread_index = thread_index;
236+
SG(server_context) = &frankenphp_local_server_ctx;
221237
/* status It is not reset by zend engine, set it to 200. */
222238
SG(sapi_headers).http_response_code = 200;
223239

@@ -485,14 +501,15 @@ static int frankenphp_worker_request_startup() {
485501
PHP_FUNCTION(frankenphp_finish_request) { /* {{{ */
486502
ZEND_PARSE_PARAMETERS_NONE();
487503

488-
if (go_is_context_done(thread_index)) {
504+
uintptr_t idx = frankenphp_thread_index();
505+
if (go_is_context_done(idx)) {
489506
RETURN_FALSE;
490507
}
491508

492509
php_output_end_all();
493510
php_header();
494511

495-
go_frankenphp_finish_php_request(thread_index);
512+
go_frankenphp_finish_php_request(idx);
496513

497514
RETURN_TRUE;
498515
} /* }}} */
@@ -587,7 +604,7 @@ PHP_FUNCTION(frankenphp_request_headers) {
587604
ZEND_PARSE_PARAMETERS_NONE();
588605

589606
struct go_apache_request_headers_return headers =
590-
go_apache_request_headers(thread_index);
607+
go_apache_request_headers(frankenphp_thread_index());
591608

592609
array_init_size(return_value, headers.r1);
593610

@@ -786,8 +803,8 @@ PHP_FUNCTION(mercure_publish) {
786803
RETURN_THROWS();
787804
}
788805

789-
struct go_mercure_publish_return result =
790-
go_mercure_publish(thread_index, topics, data, private, id, type, retry);
806+
struct go_mercure_publish_return result = go_mercure_publish(
807+
frankenphp_thread_index(), topics, data, private, id, type, retry);
791808

792809
switch (result.r1) {
793810
case 0:
@@ -819,7 +836,7 @@ PHP_FUNCTION(frankenphp_log) {
819836
ZEND_PARSE_PARAMETERS_END();
820837

821838
char *ret = NULL;
822-
ret = go_log_attrs(thread_index, message, level, context);
839+
ret = go_log_attrs(frankenphp_thread_index(), message, level, context);
823840
if (ret != NULL) {
824841
zend_throw_exception(spl_ce_RuntimeException, ret, 0);
825842
free(ret);
@@ -923,7 +940,7 @@ static int frankenphp_deactivate(void) { return SUCCESS; }
923940

924941
static size_t frankenphp_ub_write(const char *str, size_t str_length) {
925942
struct go_ub_write_return result =
926-
go_ub_write(thread_index, (char *)str, str_length);
943+
go_ub_write(frankenphp_thread_index(), (char *)str, str_length);
927944

928945
if (result.r1) {
929946
php_handle_aborted_connection();
@@ -949,7 +966,8 @@ static int frankenphp_send_headers(sapi_headers_struct *sapi_headers) {
949966
}
950967
}
951968

952-
bool success = go_write_headers(thread_index, status, &sapi_headers->headers);
969+
bool success = go_write_headers(frankenphp_thread_index(), status,
970+
&sapi_headers->headers);
953971
if (success) {
954972
return SAPI_HEADER_SENT_SUCCESSFULLY;
955973
}
@@ -959,17 +977,17 @@ static int frankenphp_send_headers(sapi_headers_struct *sapi_headers) {
959977

960978
static void frankenphp_sapi_flush(void *server_context) {
961979
sapi_send_headers();
962-
if (go_sapi_flush(thread_index)) {
980+
if (go_sapi_flush(frankenphp_thread_index())) {
963981
php_handle_aborted_connection();
964982
}
965983
}
966984

967985
static size_t frankenphp_read_post(char *buffer, size_t count_bytes) {
968-
return go_read_post(thread_index, buffer, count_bytes);
986+
return go_read_post(frankenphp_thread_index(), buffer, count_bytes);
969987
}
970988

971989
static char *frankenphp_read_cookies(void) {
972-
return go_read_cookies(thread_index);
990+
return go_read_cookies(frankenphp_thread_index());
973991
}
974992

975993
/* all variables with well defined keys can safely be registered like this */
@@ -1145,14 +1163,14 @@ static void frankenphp_register_variables(zval *track_vars_array) {
11451163
* environment, not values added though putenv
11461164
*/
11471165
/* import environment and CGI variables from the request context in go */
1148-
go_register_server_variables(thread_index, track_vars_array);
1166+
go_register_server_variables(frankenphp_thread_index(), track_vars_array);
11491167

11501168
/* Some variables are already present in SG(request_info) */
11511169
frankenphp_register_variables_from_request_info(track_vars_array);
11521170
}
11531171

11541172
static void frankenphp_log_message(const char *message, int syslog_type_int) {
1155-
go_log(thread_index, (char *)message, syslog_type_int);
1173+
go_log(frankenphp_thread_index(), (char *)message, syslog_type_int);
11561174
}
11571175

11581176
static char *frankenphp_getenv(const char *name, size_t name_len) {

0 commit comments

Comments
 (0)