Log the cause of error when opcache cannot write to file cache (#9258)

This commit is contained in:
Arnaud Le Blanc 2022-09-03 11:23:43 +02:00 committed by GitHub
parent fb242f41ba
commit ea1287b015
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 83 additions and 8 deletions

View File

@ -0,0 +1,42 @@
--TEST--
File cache error 001
--EXTENSIONS--
opcache
posix
pcntl
--INI--
opcache.enable_cli=1
opcache.file_cache={TMP}
opcache.log_verbosity_level=2
--SKIPIF--
<?php
if (!posix_setrlimit(POSIX_RLIMIT_FSIZE, 1, 1)) die('skip Test requires setrlimit(RLIMIT_FSIZE) to work');
if (ini_parse_quantity(ini_get('opcache.jit_buffer_size')) !== 0) die('skip File cache is disabled when JIT is on');
?>
--FILE--
<?php
// Create new file to ensure that it's not cached accross test runs
$file = tempnam(sys_get_temp_dir(), 'file_cache_error');
register_shutdown_function(function () use ($file) {
unlink($file);
});
file_put_contents($file, '<?php echo "OK";');
touch($file, time() - 3600);
// Some systems will raise SIGXFSZ when RLIMIT_FSIZE is exceeded
if (defined('SIGXFSZ')) {
pcntl_signal(SIGXFSZ, SIG_IGN);
}
// Should cause writing to cache file to fail
var_dump(posix_setrlimit(POSIX_RLIMIT_FSIZE, 1, 1));
// Will attempt to write to cache file, and fail
require $file;
?>
--EXPECTF--
bool(true)
%sWarning opcache cannot write to file %s: %s
OK

View File

@ -1004,10 +1004,13 @@ static char *zend_file_cache_get_bin_file_path(zend_string *script_path)
/**
* Helper function for zend_file_cache_script_store().
*
* @return true on success, false on error
* @return true on success, false on error and errno is set to indicate the cause of the error
*/
static bool zend_file_cache_script_write(int fd, const zend_persistent_script *script, const zend_file_cache_metainfo *info, const void *buf, const zend_string *s)
{
ssize_t written;
const ssize_t total_size = (ssize_t)(sizeof(*info) + script->size + info->str_size);
#ifdef HAVE_SYS_UIO_H
const struct iovec vec[] = {
{ .iov_base = (void *)info, .iov_len = sizeof(*info) },
@ -1015,12 +1018,42 @@ static bool zend_file_cache_script_write(int fd, const zend_persistent_script *s
{ .iov_base = (void *)ZSTR_VAL(s), .iov_len = info->str_size },
};
return writev(fd, vec, sizeof(vec) / sizeof(vec[0])) == (ssize_t)(sizeof(*info) + script->size + info->str_size);
written = writev(fd, vec, sizeof(vec) / sizeof(vec[0]));
if (EXPECTED(written == total_size)) {
return true;
}
errno = written == -1 ? errno : EAGAIN;
return false;
#else
return ZEND_LONG_MAX >= (zend_long)(sizeof(*info) + script->size + info->str_size) &&
write(fd, info, sizeof(*info)) == sizeof(*info) &&
write(fd, buf, script->size) == script->size &&
write(fd, ZSTR_VAL(s), info->str_size) == info->str_size;
if (UNEXPECTED(ZEND_LONG_MAX < (zend_long)total_size)) {
# ifdef EFBIG
errno = EFBIG;
# else
errno = ERANGE;
# endif
return false;
}
written = write(fd, info, sizeof(*info));
if (UNEXPECTED(written != sizeof(*info))) {
errno = written == -1 ? errno : EAGAIN;
return false;
}
written = write(fd, buf, script->size);
if (UNEXPECTED(written != script->size)) {
errno = written == -1 ? errno : EAGAIN;
return false;
}
written = write(fd, ZSTR_VAL(s), info->str_size);
if (UNEXPECTED(written != info->str_size)) {
errno = written == -1 ? errno : EAGAIN;
return false;
}
return true;
#endif
}
@ -1095,7 +1128,7 @@ int zend_file_cache_script_store(zend_persistent_script *script, bool in_shm)
#endif
if (!zend_file_cache_script_write(fd, script, &info, buf, s)) {
zend_accel_error(ACCEL_LOG_WARNING, "opcache cannot write to file '%s'\n", filename);
zend_accel_error(ACCEL_LOG_WARNING, "opcache cannot write to file '%s': %s\n", filename, strerror(errno));
zend_string_release_ex(s, 0);
close(fd);
efree(mem);
@ -1107,7 +1140,7 @@ int zend_file_cache_script_store(zend_persistent_script *script, bool in_shm)
zend_string_release_ex(s, 0);
efree(mem);
if (zend_file_cache_flock(fd, LOCK_UN) != 0) {
zend_accel_error(ACCEL_LOG_WARNING, "opcache cannot unlock file '%s'\n", filename);
zend_accel_error(ACCEL_LOG_WARNING, "opcache cannot unlock file '%s': %s\n", filename, strerror(errno));
}
close(fd);
efree(filename);