Skip to content

Commit c02ff01

Browse files
committed
Merge branch 'master' of https://git.php.net/repository/php-src
* 'master' of https://git.php.net/repository/php-src: Added function opcache_compile_file() to load PHP scripts into cache without execution. Fixed issue #135 (segfault in interned strings if initial memory is too low)
2 parents f4ce018 + 6daa04a commit c02ff01

File tree

3 files changed

+59
-5
lines changed

3 files changed

+59
-5
lines changed

ext/opcache/ZendAccelerator.c

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1450,7 +1450,7 @@ static zend_persistent_script *compile_and_cache_file(zend_file_handle *file_han
14501450
}
14511451

14521452
/* zend_compile() replacement */
1453-
static zend_op_array *persistent_compile_file(zend_file_handle *file_handle, int type TSRMLS_DC)
1453+
zend_op_array *persistent_compile_file(zend_file_handle *file_handle, int type TSRMLS_DC)
14541454
{
14551455
zend_persistent_script *persistent_script = NULL;
14561456
char *key = NULL;
@@ -2411,14 +2411,14 @@ static inline int accel_find_sapi(TSRMLS_D)
24112411
return FAILURE;
24122412
}
24132413

2414-
static void zend_accel_init_shm(TSRMLS_D)
2414+
static int zend_accel_init_shm(TSRMLS_D)
24152415
{
24162416
zend_shared_alloc_lock(TSRMLS_C);
24172417

24182418
accel_shared_globals = zend_shared_alloc(sizeof(zend_accel_shared_globals));
24192419
if (!accel_shared_globals) {
24202420
zend_accel_error(ACCEL_LOG_FATAL, "Insufficient shared memory!");
2421-
return;
2421+
return FAILURE;
24222422
}
24232423
ZSMMG(app_shared_globals) = accel_shared_globals;
24242424

@@ -2433,7 +2433,8 @@ static void zend_accel_init_shm(TSRMLS_D)
24332433
ZCSG(interned_strings).arBuckets = zend_shared_alloc(ZCSG(interned_strings).nTableSize * sizeof(Bucket *));
24342434
ZCSG(interned_strings_start) = zend_shared_alloc((ZCG(accel_directives).interned_strings_buffer * 1024 * 1024));
24352435
if (!ZCSG(interned_strings).arBuckets || !ZCSG(interned_strings_start)) {
2436-
zend_error(E_ERROR, ACCELERATOR_PRODUCT_NAME " cannot allocate buffer for interned strings");
2436+
zend_accel_error(ACCEL_LOG_FATAL, ACCELERATOR_PRODUCT_NAME " cannot allocate buffer for interned strings");
2437+
return FAILURE;
24372438
}
24382439
ZCSG(interned_strings_end) = ZCSG(interned_strings_start) + (ZCG(accel_directives).interned_strings_buffer * 1024 * 1024);
24392440
ZCSG(interned_strings_top) = ZCSG(interned_strings_start);
@@ -2472,6 +2473,8 @@ static void zend_accel_init_shm(TSRMLS_D)
24722473
ZCSG(restart_in_progress) = 0;
24732474

24742475
zend_shared_alloc_unlock(TSRMLS_C);
2476+
2477+
return SUCCESS;
24752478
}
24762479

24772480
static void accel_globals_ctor(zend_accel_globals *accel_globals TSRMLS_DC)
@@ -2529,7 +2532,10 @@ static int accel_startup(zend_extension *extension)
25292532
/********************************************/
25302533
switch (zend_shared_alloc_startup(ZCG(accel_directives).memory_consumption)) {
25312534
case ALLOC_SUCCESS:
2532-
zend_accel_init_shm(TSRMLS_C);
2535+
if (zend_accel_init_shm(TSRMLS_C) == FAILURE) {
2536+
accel_startup_ok = 0;
2537+
return FAILURE;
2538+
}
25332539
break;
25342540
case ALLOC_FAILURE:
25352541
accel_startup_ok = 0;

ext/opcache/ZendAccelerator.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -326,6 +326,7 @@ int accelerator_shm_read_lock(TSRMLS_D);
326326
void accelerator_shm_read_unlock(TSRMLS_D);
327327

328328
char *accel_make_persistent_key_ex(zend_file_handle *file_handle, int path_length, int *key_len TSRMLS_DC);
329+
zend_op_array *persistent_compile_file(zend_file_handle *file_handle, int type TSRMLS_DC);
329330

330331
#if !defined(ZEND_DECLARE_INHERITED_CLASS_DELAYED)
331332
# define ZEND_DECLARE_INHERITED_CLASS_DELAYED 145

ext/opcache/zend_accelerator_module.c

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,10 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_opcache_get_status, 0, 0, 0)
4848
ZEND_ARG_INFO(0, fetch_scripts)
4949
ZEND_END_ARG_INFO()
5050

51+
ZEND_BEGIN_ARG_INFO_EX(arginfo_opcache_compile_file, 0, 0, 1)
52+
ZEND_ARG_INFO(0, file)
53+
ZEND_END_ARG_INFO()
54+
5155
ZEND_BEGIN_ARG_INFO_EX(arginfo_opcache_invalidate, 0, 0, 1)
5256
ZEND_ARG_INFO(0, script)
5357
ZEND_ARG_INFO(0, force)
@@ -59,12 +63,14 @@ static ZEND_FUNCTION(opcache_invalidate);
5963

6064
/* Private functions */
6165
static ZEND_FUNCTION(opcache_get_status);
66+
static ZEND_FUNCTION(opcache_compile_file);
6267
static ZEND_FUNCTION(opcache_get_configuration);
6368

6469
static zend_function_entry accel_functions[] = {
6570
/* User functions */
6671
ZEND_FE(opcache_reset, arginfo_opcache_none)
6772
ZEND_FE(opcache_invalidate, arginfo_opcache_invalidate)
73+
ZEND_FE(opcache_compile_file, arginfo_opcache_compile_file)
6874
/* Private functions */
6975
ZEND_FE(opcache_get_configuration, arginfo_opcache_none)
7076
ZEND_FE(opcache_get_status, arginfo_opcache_get_status)
@@ -709,3 +715,44 @@ static ZEND_FUNCTION(opcache_invalidate)
709715
RETURN_FALSE;
710716
}
711717
}
718+
719+
static ZEND_FUNCTION(opcache_compile_file)
720+
{
721+
char *script_name;
722+
int script_name_len;
723+
zend_file_handle handle;
724+
zend_op_array *op_array = NULL;
725+
zend_execute_data *orig_execute_data = NULL;
726+
727+
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &script_name, &script_name_len) == FAILURE) {
728+
return;
729+
}
730+
731+
if (!ZCG(enabled) || !accel_startup_ok || !ZCSG(accelerator_enabled)) {
732+
zend_error(E_NOTICE, ACCELERATOR_PRODUCT_NAME " seems to be disabled, can't compile file");
733+
RETURN_FALSE;
734+
}
735+
736+
handle.filename = script_name;
737+
handle.free_filename = 0;
738+
handle.opened_path = NULL;
739+
handle.type = ZEND_HANDLE_FILENAME;
740+
741+
orig_execute_data = EG(current_execute_data);
742+
743+
zend_try {
744+
op_array = persistent_compile_file(&handle, ZEND_INCLUDE TSRMLS_CC);
745+
} zend_catch {
746+
EG(current_execute_data) = orig_execute_data;
747+
zend_error(E_WARNING, ACCELERATOR_PRODUCT_NAME " could not compile file %s" TSRMLS_CC, handle.filename);
748+
} zend_end_try();
749+
750+
if(op_array != NULL) {
751+
destroy_op_array(op_array TSRMLS_CC);
752+
efree(op_array);
753+
RETVAL_TRUE;
754+
} else {
755+
RETVAL_FALSE;
756+
}
757+
zend_destroy_file_handle(&handle TSRMLS_CC);
758+
}

0 commit comments

Comments
 (0)