Skip to content

Commit ef12ecd

Browse files
committed
fix: session GC fork
1 parent 4c027ea commit ef12ecd

2 files changed

Lines changed: 10 additions & 15 deletions

File tree

ext/session/php_session.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,8 @@ typedef struct _php_ps_globals {
146146
zend_string *session_started_filename;
147147
uint32_t session_started_lineno;
148148
int module_number;
149+
/* Unused since the GC probability draw was made stateless; retained only
150+
* to preserve struct layout (ABI) on stable branches. */
149151
php_random_status_state_pcgoneseq128xslrr64 random_state;
150152
php_random_algo_with_state random;
151153
zend_long gc_probability;

ext/session/session.c

Lines changed: 8 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -392,9 +392,15 @@ static zend_long php_session_gc(bool immediate)
392392

393393
/* GC must be done before reading session data. */
394394
if ((PS(mod_data) || PS(mod_user_implemented))) {
395-
/* Use probability-based GC if not forced and probability is configured */
396395
if (!collect && PS(gc_probability) > 0) {
397-
collect = php_random_range(PS(random), 0, PS(gc_divisor) - 1) < PS(gc_probability);
396+
/* Draw fresh entropy per request instead of using the per-process
397+
* PS(random) state. The latter is seeded once in GINIT, which runs
398+
* before SAPIs such as PHP-FPM fork their workers, so every worker
399+
* would inherit and replay the same GC-decision sequence. */
400+
uint32_t rand_val;
401+
if (php_random_bytes_silent(&rand_val, sizeof(rand_val)) == SUCCESS) {
402+
collect = (rand_val % (uint32_t) PS(gc_divisor)) < (uint32_t) PS(gc_probability);
403+
}
398404
}
399405

400406
if (collect) {
@@ -2886,19 +2892,6 @@ static PHP_GINIT_FUNCTION(ps)
28862892
ZVAL_UNDEF(&ps_globals->mod_user_names.ps_validate_sid);
28872893
ZVAL_UNDEF(&ps_globals->mod_user_names.ps_update_timestamp);
28882894
ZVAL_UNDEF(&ps_globals->http_session_vars);
2889-
2890-
ps_globals->random = (php_random_algo_with_state){
2891-
.algo = &php_random_algo_pcgoneseq128xslrr64,
2892-
.state = &ps_globals->random_state,
2893-
};
2894-
php_random_uint128_t seed;
2895-
if (php_random_bytes_silent(&seed, sizeof(seed)) == FAILURE) {
2896-
seed = php_random_uint128_constant(
2897-
php_random_generate_fallback_seed(),
2898-
php_random_generate_fallback_seed()
2899-
);
2900-
}
2901-
php_random_pcgoneseq128xslrr64_seed128(ps_globals->random.state, seed);
29022895
}
29032896

29042897
static PHP_MINIT_FUNCTION(session)

0 commit comments

Comments
 (0)