@@ -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
97112static bool is_forked_child = false;
98113static void frankenphp_fork_child (void ) { is_forked_child = true; }
@@ -217,7 +232,8 @@ void frankenphp_update_local_thread_context(bool is_worker) {
217232static 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() {
485501PHP_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
924941static 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
960978static 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
967985static 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
971989static 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
11541172static 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
11581176static char * frankenphp_getenv (const char * name , size_t name_len ) {
0 commit comments