Skip to content

Commit bcee2fd

Browse files
mhagstrandnikic
authored andcommitted
Fixed bug in zend_accel_error() and cleaned up kill_all_lockers()
1. zend_accel_error was only executing clean up if log_verbosity_level is high enough to log 2. Cleaned up kill_all_lockers function and fixed comments.
1 parent fe49fd7 commit bcee2fd

File tree

3 files changed

+75
-39
lines changed

3 files changed

+75
-39
lines changed

ext/opcache/ZendAccelerator.c

+21-6
Original file line numberDiff line numberDiff line change
@@ -619,27 +619,42 @@ static void accel_use_shm_interned_strings(void)
619619
#ifndef ZEND_WIN32
620620
static inline void kill_all_lockers(struct flock *mem_usage_check)
621621
{
622-
int tries = 10;
623-
622+
int success, tries;
624623
/* so that other process won't try to force while we are busy cleaning up */
625624
ZCSG(force_restart_time) = 0;
626625
while (mem_usage_check->l_pid > 0) {
626+
/* Clear previous errno, reset success and tries */
627+
errno = 0;
628+
success = 0;
629+
tries = 10;
630+
627631
while (tries--) {
628-
zend_accel_error(ACCEL_LOG_WARNING, "Killed locker %d", mem_usage_check->l_pid);
632+
zend_accel_error(ACCEL_LOG_WARNING, "Attempting to kill locker %d", mem_usage_check->l_pid);
629633
if (kill(mem_usage_check->l_pid, SIGKILL)) {
634+
if (errno == ESRCH) {
635+
/* Process died before the signal was sent */
636+
success = 1;
637+
zend_accel_error(ACCEL_LOG_WARNING, "Process %d died before SIGKILL was sent", mem_usage_check->l_pid);
638+
}
630639
break;
631640
}
632641
/* give it a chance to die */
633642
usleep(20000);
634643
if (kill(mem_usage_check->l_pid, 0)) {
635-
/* can't kill it */
644+
if (errno == ESRCH) {
645+
/* successfully killed locker, process no longer exists */
646+
success = 1;
647+
zend_accel_error(ACCEL_LOG_WARNING, "Killed locker %d", mem_usage_check->l_pid);
648+
}
636649
break;
637650
}
638651
usleep(10000);
639652
}
640-
if (!tries) {
641-
zend_accel_error(ACCEL_LOG_WARNING, "Can't kill %d after 10 tries!", mem_usage_check->l_pid);
653+
if (!success) {
654+
/* errno is not ESRCH or we ran out of tries to kill the locker */
642655
ZCSG(force_restart_time) = time(NULL); /* restore forced restart request */
656+
/* cannot kill the locker, bail out with error */
657+
zend_accel_error(ACCEL_LOG_ERROR, "Cannot kill process %d: %s!", mem_usage_check->l_pid, strerror(errno));
643658
}
644659

645660
mem_usage_check->l_type = F_WRLCK;
+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
--TEST--
2+
Test ACCEL_LOG_FATAL will cause the process to die even if not logged
3+
--DESCRIPTION--
4+
This test forces the opcache to error by setting memory_comsumption very large.
5+
The resulting ACCEL_LOG_FATAL should cause php to die.
6+
The process should die regardless of the log_verbosity_level.
7+
--INI--
8+
opcache.enable=1
9+
opcache.enable_cli=1
10+
opcache.memory_consumption=999999999
11+
opcache.log_verbosity_level=-1
12+
--SKIPIF--
13+
<?php require_once('skipif.inc'); ?>
14+
--FILE--
15+
<?php
16+
var_dump("Script should fail");
17+
?>
18+
--EXPECTF--
19+

ext/opcache/zend_accelerator_debug.c

+35-33
Original file line numberDiff line numberDiff line change
@@ -30,22 +30,20 @@
3030

3131
void zend_accel_error(int type, const char *format, ...)
3232
{
33-
va_list args;
33+
va_list args;
3434
time_t timestamp;
3535
char *time_string;
3636
FILE * fLog = NULL;
3737

38-
if (type > ZCG(accel_directives).log_verbosity_level) {
39-
return;
40-
}
38+
if (type <= ZCG(accel_directives).log_verbosity_level) {
4139

4240
timestamp = time(NULL);
4341
time_string = asctime(localtime(&timestamp));
4442
time_string[24] = 0;
4543

4644
if (!ZCG(accel_directives).error_log ||
47-
!*ZCG(accel_directives).error_log ||
48-
strcmp(ZCG(accel_directives).error_log, "stderr") == 0) {
45+
!*ZCG(accel_directives).error_log ||
46+
strcmp(ZCG(accel_directives).error_log, "stderr") == 0) {
4947

5048
fLog = stderr;
5149
} else {
@@ -56,33 +54,40 @@ void zend_accel_error(int type, const char *format, ...)
5654
}
5755

5856
#ifdef ZTS
59-
fprintf(fLog, "%s (" ZEND_ULONG_FMT "): ", time_string, (zend_ulong)tsrm_thread_id());
57+
fprintf(fLog, "%s (" ZEND_ULONG_FMT "): ", time_string, (zend_ulong)tsrm_thread_id());
6058
#else
61-
fprintf(fLog, "%s (%d): ", time_string, getpid());
59+
fprintf(fLog, "%s (%d): ", time_string, getpid());
6260
#endif
6361

64-
switch (type) {
65-
case ACCEL_LOG_FATAL:
66-
fprintf(fLog, "Fatal Error ");
67-
break;
68-
case ACCEL_LOG_ERROR:
69-
fprintf(fLog, "Error ");
70-
break;
71-
case ACCEL_LOG_WARNING:
72-
fprintf(fLog, "Warning ");
73-
break;
74-
case ACCEL_LOG_INFO:
75-
fprintf(fLog, "Message ");
76-
break;
77-
case ACCEL_LOG_DEBUG:
78-
fprintf(fLog, "Debug ");
79-
break;
80-
}
62+
switch (type) {
63+
case ACCEL_LOG_FATAL:
64+
fprintf(fLog, "Fatal Error ");
65+
break;
66+
case ACCEL_LOG_ERROR:
67+
fprintf(fLog, "Error ");
68+
break;
69+
case ACCEL_LOG_WARNING:
70+
fprintf(fLog, "Warning ");
71+
break;
72+
case ACCEL_LOG_INFO:
73+
fprintf(fLog, "Message ");
74+
break;
75+
case ACCEL_LOG_DEBUG:
76+
fprintf(fLog, "Debug ");
77+
break;
78+
}
79+
80+
va_start(args, format);
81+
vfprintf(fLog, format, args);
82+
va_end(args);
83+
fprintf(fLog, "\n");
8184

82-
va_start(args, format);
83-
vfprintf(fLog, format, args);
84-
va_end(args);
85-
fprintf(fLog, "\n");
85+
fflush(fLog);
86+
if (fLog != stderr) {
87+
fclose(fLog);
88+
}
89+
}
90+
/* perform error handling even without logging the error */
8691
switch (type) {
8792
case ACCEL_LOG_ERROR:
8893
zend_bailout();
@@ -91,8 +96,5 @@ void zend_accel_error(int type, const char *format, ...)
9196
exit(-2);
9297
break;
9398
}
94-
fflush(fLog);
95-
if (fLog != stderr) {
96-
fclose(fLog);
97-
}
99+
98100
}

0 commit comments

Comments
 (0)