From 1fb3d841bbb6444424539ef3065fc15273f32351 Mon Sep 17 00:00:00 2001 From: Kamil Tekiela Date: Sun, 8 Nov 2026 16:21:22 +0000 Subject: [PATCH] Fixed bug GH-12010 (opcache crashes on high volume IIS servers --- NEWS | 2 ++ ext/opcache/ZendAccelerator.c | 13 +++++++++++++ ext/opcache/shared_alloc_win32.c | 4 ++-- 3 files changed, 17 insertions(+), 2 deletions(-) diff --git a/NEWS b/NEWS index 0dd463bcdc75..9239dc08ecf6 100644 --- a/NEWS +++ b/NEWS @@ -34,6 +34,8 @@ PHP NEWS conversion in JIT). (Jorg Sowa) . Fixed bug GH-25037 (Function JIT ENTRY live var assertion). (Ilia Alshanetsky) + . Fixed bug GH-12010 (opcache crashes on high volume IIS servers (Windows)). + (Kamil Tekiela) - SOAP: . Fixed bug GH-25267 (NULL dereference in to_xml_any() with integer key). diff --git a/ext/opcache/ZendAccelerator.c b/ext/opcache/ZendAccelerator.c index e56904d7efb8..e34e08735e4b 100644 --- a/ext/opcache/ZendAccelerator.c +++ b/ext/opcache/ZendAccelerator.c @@ -3264,6 +3264,9 @@ static zend_result accel_post_startup(void) file_cache_only = ZCG(accel_directives).file_cache_only; if (!file_cache_only) { size_t shm_size = ZCG(accel_directives).memory_consumption; +#ifdef ZEND_WIN32 + bool created = false; +#endif #ifdef HAVE_JIT size_t jit_size = 0; bool reattached = false; @@ -3287,6 +3290,9 @@ static zend_result accel_post_startup(void) switch (zend_shared_alloc_startup(shm_size, 0)) { #endif case ALLOC_SUCCESS: +#ifdef ZEND_WIN32 + created = true; +#endif if (zend_accel_init_shm() == FAILURE) { accel_startup_ok = false; return FAILURE; @@ -3346,6 +3352,13 @@ static zend_result accel_post_startup(void) zend_shared_alloc_save_state(); zend_shared_alloc_unlock(); +#ifdef ZEND_WIN32 + if (created) { + /* create_segments() kept the mutex locked until the segment is initialized. */ + zend_shared_alloc_unlock_win32(); + } +#endif + SHM_PROTECT(); } else if (!ZCG(accel_directives).file_cache) { accel_startup_ok = false; diff --git a/ext/opcache/shared_alloc_win32.c b/ext/opcache/shared_alloc_win32.c index 5e37cedcb4dd..9dda1d3103eb 100644 --- a/ext/opcache/shared_alloc_win32.c +++ b/ext/opcache/shared_alloc_win32.c @@ -329,8 +329,8 @@ static int create_segments(size_t requested_size, zend_shared_segment ***shared_ shared_segment->pos = ACCEL_BASE_POINTER_SIZE; shared_segment->size = requested_size - ACCEL_BASE_POINTER_SIZE; - zend_shared_alloc_unlock_win32(); - + /* Keep the mutex locked. Other processes must not reattach before the + * segment is initialized. accel_post_startup() unlocks it after that. */ return ALLOC_SUCCESS; }