Skip to content

Commit a449bb5

Browse files
committed
Fix bug #76895
There are two parts here: First, opcache should not be blocking signals while invoking compile_file. Second, we should have noticed this issue a long time ago, but apparently we don't use zend_signal_deactivate as part of the standard shutdown sequence. In addition to calling deactivate, also make sure that we always check for zero depth, independent of SIGG(check), which is currently not enabled.
1 parent 8f384be commit a449bb5

File tree

3 files changed

+29
-5
lines changed

3 files changed

+29
-5
lines changed

Zend/zend_signal.c

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -330,20 +330,21 @@ void zend_signal_activate(void)
330330

331331
SIGG(active) = 1;
332332
SIGG(depth) = 0;
333+
SIGG(check) = ZEND_DEBUG;
333334
} /* }}} */
334335

335336
/* {{{ zend_signal_deactivate
336337
* */
337338
void zend_signal_deactivate(void)
338339
{
339-
340340
if (SIGG(check)) {
341341
size_t x;
342342
struct sigaction sa;
343343

344344
if (SIGG(depth) != 0) {
345345
zend_error(E_CORE_WARNING, "zend_signal: shutdown with non-zero blocking depth (%d)", SIGG(depth));
346346
}
347+
347348
/* did anyone steal our installed handler */
348349
for (x = 0; x < sizeof(zend_sigs) / sizeof(*zend_sigs); x++) {
349350
sigaction(zend_sigs[x], NULL, &sa);
@@ -353,12 +354,21 @@ void zend_signal_deactivate(void)
353354
}
354355
}
355356

356-
SIGNAL_BEGIN_CRITICAL();
357-
SIGG(active) = 0;
357+
/* After active=0 is set, signal handlers will be called directly and other
358+
* state that is reset below will not be accessed. */
359+
*((volatile int *) &SIGG(active)) = 0;
360+
358361
SIGG(running) = 0;
359362
SIGG(blocked) = 0;
360363
SIGG(depth) = 0;
361-
SIGNAL_END_CRITICAL();
364+
365+
/* If there are any queued signals because of a missed unblock, drop them. */
366+
if (SIGG(phead) && SIGG(ptail)) {
367+
SIGG(ptail)->next = SIGG(pavail);
368+
SIGG(pavail) = SIGG(phead);
369+
SIGG(phead) = NULL;
370+
SIGG(ptail) = NULL;
371+
}
362372
}
363373
/* }}} */
364374

ext/opcache/ZendAccelerator.c

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1570,7 +1570,9 @@ static zend_persistent_script *opcache_compile_file(zend_file_handle *file_handl
15701570

15711571
/* check blacklist right after ensuring that file was opened */
15721572
if (file_handle->opened_path && zend_accel_blacklist_is_blacklisted(&accel_blacklist, ZSTR_VAL(file_handle->opened_path))) {
1573+
SHM_UNPROTECT();
15731574
ZCSG(blacklist_misses)++;
1575+
SHM_PROTECT();
15741576
*op_array_p = accelerator_orig_compile_file(file_handle, type);
15751577
return NULL;
15761578
}
@@ -1601,7 +1603,9 @@ static zend_persistent_script *opcache_compile_file(zend_file_handle *file_handl
16011603
}
16021604

16031605
if (ZCG(accel_directives).max_file_size > 0 && size > (size_t)ZCG(accel_directives).max_file_size) {
1606+
SHM_UNPROTECT();
16041607
ZCSG(blacklist_misses)++;
1608+
SHM_PROTECT();
16051609
*op_array_p = accelerator_orig_compile_file(file_handle, type);
16061610
return NULL;
16071611
}
@@ -2003,11 +2007,16 @@ zend_op_array *persistent_compile_file(zend_file_handle *file_handle, int type)
20032007
return accelerator_orig_compile_file(file_handle, type);
20042008
}
20052009

2010+
SHM_PROTECT();
2011+
HANDLE_UNBLOCK_INTERRUPTIONS();
2012+
persistent_script = opcache_compile_file(file_handle, type, key, &op_array);
2013+
HANDLE_BLOCK_INTERRUPTIONS();
2014+
SHM_UNPROTECT();
2015+
20062016
/* Try and cache the script and assume that it is returned from_shared_memory.
20072017
* If it isn't compile_and_cache_file() changes the flag to 0
20082018
*/
20092019
from_shared_memory = 0;
2010-
persistent_script = opcache_compile_file(file_handle, type, key, &op_array);
20112020
if (persistent_script) {
20122021
persistent_script = cache_script_in_shared_memory(persistent_script, key, key ? key_length : 0, &from_shared_memory);
20132022
}

main/main.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1932,6 +1932,11 @@ void php_request_shutdown(void *dummy)
19321932
zend_unset_timeout();
19331933
} zend_end_try();
19341934

1935+
/* 17. Deactivate Zend signals */
1936+
#ifdef ZEND_SIGNALS
1937+
zend_signal_deactivate();
1938+
#endif
1939+
19351940
#ifdef PHP_WIN32
19361941
if (PG(com_initialized)) {
19371942
CoUninitialize();

0 commit comments

Comments
 (0)