PHP  
 PHP: Test and Code Coverage Analysis
downloads | QA | documentation | faq | getting help | mailing lists | reporting bugs | php.net sites | links | my php.net 
 

LCOV - code coverage report
Current view: top level - ext/opcache - ZendAccelerator.c (source / functions) Hit Total Coverage
Test: PHP Code Coverage Lines: 800 1389 57.6 %
Date: 2016-09-27 Functions: 47 65 72.3 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :    +----------------------------------------------------------------------+
       3             :    | Zend OPcache                                                         |
       4             :    +----------------------------------------------------------------------+
       5             :    | Copyright (c) 1998-2016 The PHP Group                                |
       6             :    +----------------------------------------------------------------------+
       7             :    | This source file is subject to version 3.01 of the PHP license,      |
       8             :    | that is bundled with this package in the file LICENSE, and is        |
       9             :    | available through the world-wide-web at the following url:           |
      10             :    | http://www.php.net/license/3_01.txt                                  |
      11             :    | If you did not receive a copy of the PHP license and are unable to   |
      12             :    | obtain it through the world-wide-web, please send a note to          |
      13             :    | license@php.net so we can mail you a copy immediately.               |
      14             :    +----------------------------------------------------------------------+
      15             :    | Authors: Andi Gutmans <andi@zend.com>                                |
      16             :    |          Zeev Suraski <zeev@zend.com>                                |
      17             :    |          Stanislav Malyshev <stas@zend.com>                          |
      18             :    |          Dmitry Stogov <dmitry@zend.com>                             |
      19             :    +----------------------------------------------------------------------+
      20             : */
      21             : 
      22             : #include "main/php.h"
      23             : #include "main/php_globals.h"
      24             : #include "zend.h"
      25             : #include "zend_extensions.h"
      26             : #include "zend_compile.h"
      27             : #include "ZendAccelerator.h"
      28             : #include "zend_persist.h"
      29             : #include "zend_shared_alloc.h"
      30             : #include "zend_accelerator_module.h"
      31             : #include "zend_accelerator_blacklist.h"
      32             : #include "zend_list.h"
      33             : #include "zend_execute.h"
      34             : #include "main/SAPI.h"
      35             : #include "main/php_streams.h"
      36             : #include "main/php_open_temporary_file.h"
      37             : #include "zend_API.h"
      38             : #include "zend_ini.h"
      39             : #include "zend_virtual_cwd.h"
      40             : #include "zend_accelerator_util_funcs.h"
      41             : #include "zend_accelerator_hash.h"
      42             : #include "ext/pcre/php_pcre.h"
      43             : #include "ext/standard/md5.h"
      44             : 
      45             : #ifdef HAVE_OPCACHE_FILE_CACHE
      46             : # include "zend_file_cache.h"
      47             : #endif
      48             : 
      49             : #ifndef ZEND_WIN32
      50             : #include  <netdb.h>
      51             : #endif
      52             : 
      53             : #ifdef ZEND_WIN32
      54             : typedef int uid_t;
      55             : typedef int gid_t;
      56             : #include <io.h>
      57             : #endif
      58             : 
      59             : #ifndef ZEND_WIN32
      60             : # include <sys/time.h>
      61             : #else
      62             : # include <process.h>
      63             : #endif
      64             : 
      65             : #ifdef HAVE_UNISTD_H
      66             : # include <unistd.h>
      67             : #endif
      68             : #include <fcntl.h>
      69             : #include <signal.h>
      70             : #include <time.h>
      71             : 
      72             : #ifndef ZEND_WIN32
      73             : # include <sys/types.h>
      74             : # include <sys/ipc.h>
      75             : #endif
      76             : 
      77             : #include <sys/stat.h>
      78             : #include <errno.h>
      79             : 
      80             : #define SHM_PROTECT() \
      81             :         do { \
      82             :                 if (ZCG(accel_directives).protect_memory) { \
      83             :                         zend_accel_shared_protect(1); \
      84             :                 } \
      85             :         } while (0)
      86             : #define SHM_UNPROTECT() \
      87             :         do { \
      88             :                 if (ZCG(accel_directives).protect_memory) { \
      89             :                         zend_accel_shared_protect(0); \
      90             :                 } \
      91             :         } while (0)
      92             : 
      93             : ZEND_EXTENSION();
      94             : 
      95             : #ifndef ZTS
      96             : zend_accel_globals accel_globals;
      97             : #else
      98             : int accel_globals_id;
      99             : #if defined(COMPILE_DL_OPCACHE)
     100             : ZEND_TSRMLS_CACHE_DEFINE()
     101             : #endif
     102             : #endif
     103             : 
     104             : /* Points to the structure shared across all PHP processes */
     105             : zend_accel_shared_globals *accel_shared_globals = NULL;
     106             : 
     107             : /* true globals, no need for thread safety */
     108             : zend_bool accel_startup_ok = 0;
     109             : static char *zps_failure_reason = NULL;
     110             : char *zps_api_failure_reason = NULL;
     111             : #if ENABLE_FILE_CACHE_FALLBACK
     112             : zend_bool fallback_process = 0; /* process uses file cache fallback */
     113             : #endif
     114             : 
     115             : static zend_op_array *(*accelerator_orig_compile_file)(zend_file_handle *file_handle, int type);
     116             : static int (*accelerator_orig_zend_stream_open_function)(const char *filename, zend_file_handle *handle );
     117             : static zend_string *(*accelerator_orig_zend_resolve_path)(const char *filename, int filename_len);
     118             : static void (*orig_chdir)(INTERNAL_FUNCTION_PARAMETERS) = NULL;
     119             : static ZEND_INI_MH((*orig_include_path_on_modify)) = NULL;
     120             : 
     121             : #ifdef ZEND_WIN32
     122             : # define INCREMENT(v) InterlockedIncrement64(&ZCSG(v))
     123             : # define DECREMENT(v) InterlockedDecrement64(&ZCSG(v))
     124             : # define LOCKVAL(v)   (ZCSG(v))
     125             : #endif
     126             : 
     127             : #ifdef ZEND_WIN32
     128             : static time_t zend_accel_get_time(void)
     129             : {
     130             :         FILETIME now;
     131             :         GetSystemTimeAsFileTime(&now);
     132             : 
     133             :         return (time_t) ((((((__int64)now.dwHighDateTime) << 32)|now.dwLowDateTime) - 116444736000000000L)/10000000);
     134             : }
     135             : #else
     136             : # define zend_accel_get_time() time(NULL)
     137             : #endif
     138             : 
     139         569 : static inline int is_stream_path(const char *filename)
     140             : {
     141             :         const char *p;
     142             : 
     143        6069 :         for (p = filename;
     144        2211 :              (*p >= 'a' && *p <= 'z') ||
     145         655 :              (*p >= 'A' && *p <= 'Z') ||
     146         690 :              (*p >= '0' && *p <= '9') ||
     147        1944 :              *p == '+' || *p == '-' || *p == '.';
     148         863 :              p++);
     149         569 :         return ((p != filename) && (p[0] == ':') && (p[1] == '/') && (p[2] == '/'));
     150             : }
     151             : 
     152          30 : static inline int is_cacheable_stream_path(const char *filename)
     153             : {
     154          60 :         return memcmp(filename, "file://", sizeof("file://") - 1) == 0 ||
     155          30 :                memcmp(filename, "phar://", sizeof("phar://") - 1) == 0;
     156             : }
     157             : 
     158             : /* O+ overrides PHP chdir() function and remembers the current working directory
     159             :  * in ZCG(cwd) and ZCG(cwd_len). Later accel_getcwd() can use stored value and
     160             :  * avoid getcwd() call.
     161             :  */
     162           0 : static ZEND_FUNCTION(accel_chdir)
     163             : {
     164             :         char cwd[MAXPATHLEN];
     165             : 
     166           0 :         orig_chdir(INTERNAL_FUNCTION_PARAM_PASSTHRU);
     167           0 :         if (VCWD_GETCWD(cwd, MAXPATHLEN)) {
     168           0 :                 if (ZCG(cwd)) {
     169           0 :                         zend_string_release(ZCG(cwd));
     170             :                 }
     171           0 :                 ZCG(cwd) = zend_string_init(cwd, strlen(cwd), 0);
     172             :         } else {
     173           0 :                 if (ZCG(cwd)) {
     174           0 :                         zend_string_release(ZCG(cwd));
     175           0 :                         ZCG(cwd) = NULL;
     176             :                 }
     177             :         }
     178           0 :         ZCG(cwd_key_len) = 0;
     179           0 :         ZCG(cwd_check) = 1;
     180           0 : }
     181             : 
     182          77 : static inline zend_string* accel_getcwd(void)
     183             : {
     184          77 :         if (ZCG(cwd)) {
     185           0 :                 return ZCG(cwd);
     186             :         } else {
     187             :                 char cwd[MAXPATHLEN + 1];
     188             : 
     189          77 :                 if (!VCWD_GETCWD(cwd, MAXPATHLEN)) {
     190           0 :                         return NULL;
     191             :                 }
     192         154 :                 ZCG(cwd) = zend_string_init(cwd, strlen(cwd), 0);
     193          77 :                 ZCG(cwd_key_len) = 0;
     194          77 :                 ZCG(cwd_check) = 1;
     195          77 :                 return ZCG(cwd);
     196             :         }
     197             : }
     198             : 
     199           0 : void zend_accel_schedule_restart_if_necessary(zend_accel_restart_reason reason)
     200             : {
     201           0 :         if ((((double) ZSMMG(wasted_shared_memory)) / ZCG(accel_directives).memory_consumption) >= ZCG(accel_directives).max_wasted_percentage) {
     202           0 :                 zend_accel_schedule_restart(reason);
     203             :         }
     204           0 : }
     205             : 
     206             : /* O+ tracks changes of "include_path" directive. It stores all the requested
     207             :  * values in ZCG(include_paths) shared hash table, current value in
     208             :  * ZCG(include_path)/ZCG(include_path_len) and one letter "path key" in
     209             :  * ZCG(include_path_key).
     210             :  */
     211           8 : static ZEND_INI_MH(accel_include_path_on_modify)
     212             : {
     213           8 :         int ret = orig_include_path_on_modify(entry, new_value, mh_arg1, mh_arg2, mh_arg3, stage);
     214             : 
     215           8 :         if (ret == SUCCESS) {
     216           8 :                 ZCG(include_path) = new_value;
     217           8 :                 ZCG(include_path_key_len) = 0;
     218           8 :                 ZCG(include_path_check) = 1;
     219             :         }
     220           8 :         return ret;
     221             : }
     222             : 
     223           0 : static inline void accel_restart_enter(void)
     224             : {
     225             : #ifdef ZEND_WIN32
     226             :         INCREMENT(restart_in);
     227             : #else
     228             : # ifdef _AIX
     229             :         static FLOCK_STRUCTURE(restart_in_progress, F_WRLCK, SEEK_SET, 2, 1);
     230             : # else
     231             :         static const FLOCK_STRUCTURE(restart_in_progress, F_WRLCK, SEEK_SET, 2, 1);
     232             : #endif
     233             : 
     234           0 :         if (fcntl(lock_file, F_SETLK, &restart_in_progress) == -1) {
     235           0 :                 zend_accel_error(ACCEL_LOG_DEBUG, "RestartC(+1):  %s (%d)", strerror(errno), errno);
     236             :         }
     237             : #endif
     238           0 :         ZCSG(restart_in_progress) = 1;
     239           0 : }
     240             : 
     241           0 : static inline void accel_restart_leave(void)
     242             : {
     243             : #ifdef ZEND_WIN32
     244             :         ZCSG(restart_in_progress) = 0;
     245             :         DECREMENT(restart_in);
     246             : #else
     247             : # ifdef _AIX
     248             :         static FLOCK_STRUCTURE(restart_finished, F_UNLCK, SEEK_SET, 2, 1);
     249             : # else
     250             :         static const FLOCK_STRUCTURE(restart_finished, F_UNLCK, SEEK_SET, 2, 1);
     251             : # endif
     252             : 
     253           0 :         ZCSG(restart_in_progress) = 0;
     254           0 :         if (fcntl(lock_file, F_SETLK, &restart_finished) == -1) {
     255           0 :                 zend_accel_error(ACCEL_LOG_DEBUG, "RestartC(-1):  %s (%d)", strerror(errno), errno);
     256             :         }
     257             : #endif
     258           0 : }
     259             : 
     260           0 : static inline int accel_restart_is_active(void)
     261             : {
     262           0 :         if (ZCSG(restart_in_progress)) {
     263             : #ifndef ZEND_WIN32
     264           0 :                 FLOCK_STRUCTURE(restart_check, F_WRLCK, SEEK_SET, 2, 1);
     265             : 
     266           0 :                 if (fcntl(lock_file, F_GETLK, &restart_check) == -1) {
     267           0 :                         zend_accel_error(ACCEL_LOG_DEBUG, "RestartC:  %s (%d)", strerror(errno), errno);
     268           0 :                         return FAILURE;
     269             :                 }
     270           0 :                 if (restart_check.l_type == F_UNLCK) {
     271           0 :                         ZCSG(restart_in_progress) = 0;
     272           0 :                         return 0;
     273             :                 } else {
     274           0 :                         return 1;
     275             :                 }
     276             : #else
     277             :                 return LOCKVAL(restart_in) != 0;
     278             : #endif
     279             :         }
     280           0 :         return 0;
     281             : }
     282             : 
     283             : /* Creates a read lock for SHM access */
     284         476 : static inline int accel_activate_add(void)
     285             : {
     286             : #ifdef ZEND_WIN32
     287             :         INCREMENT(mem_usage);
     288             : #else
     289             : # ifdef _AIX
     290             :         static FLOCK_STRUCTURE(mem_usage_lock, F_RDLCK, SEEK_SET, 1, 1);
     291             : # else
     292             :         static const FLOCK_STRUCTURE(mem_usage_lock, F_RDLCK, SEEK_SET, 1, 1);
     293             : # endif
     294             : 
     295         476 :         if (fcntl(lock_file, F_SETLK, &mem_usage_lock) == -1) {
     296           0 :                 zend_accel_error(ACCEL_LOG_DEBUG, "UpdateC(+1):  %s (%d)", strerror(errno), errno);
     297           0 :                 return FAILURE;
     298             :         }
     299             : #endif
     300         476 :         return SUCCESS;
     301             : }
     302             : 
     303             : /* Releases a lock for SHM access */
     304           0 : static inline void accel_deactivate_sub(void)
     305             : {
     306             : #ifdef ZEND_WIN32
     307             :         if (ZCG(counted)) {
     308             :                 DECREMENT(mem_usage);
     309             :                 ZCG(counted) = 0;
     310             :         }
     311             : #else
     312             : # ifdef _AIX
     313             :         static FLOCK_STRUCTURE(mem_usage_unlock, F_UNLCK, SEEK_SET, 1, 1);
     314             : # else
     315             :         static const FLOCK_STRUCTURE(mem_usage_unlock, F_UNLCK, SEEK_SET, 1, 1);
     316             : # endif
     317             : 
     318           0 :         if (fcntl(lock_file, F_SETLK, &mem_usage_unlock) == -1) {
     319           0 :                 zend_accel_error(ACCEL_LOG_DEBUG, "UpdateC(-1):  %s (%d)", strerror(errno), errno);
     320             :         }
     321             : #endif
     322           0 : }
     323             : 
     324         478 : static inline void accel_unlock_all(void)
     325             : {
     326             : #ifdef ZEND_WIN32
     327             :         accel_deactivate_sub();
     328             : #else
     329             : # ifdef _AIX
     330             :         static FLOCK_STRUCTURE(mem_usage_unlock_all, F_UNLCK, SEEK_SET, 0, 0);
     331             : # else
     332             :         static const FLOCK_STRUCTURE(mem_usage_unlock_all, F_UNLCK, SEEK_SET, 0, 0);
     333             : # endif
     334             : 
     335         478 :         if (fcntl(lock_file, F_SETLK, &mem_usage_unlock_all) == -1) {
     336           1 :                 zend_accel_error(ACCEL_LOG_DEBUG, "UnlockAll:  %s (%d)", strerror(errno), errno);
     337             :         }
     338             : #endif
     339         478 : }
     340             : 
     341             : /* Interned strings support */
     342             : static zend_string *(*orig_new_interned_string)(zend_string *str);
     343             : static void (*orig_interned_strings_snapshot)(void);
     344             : static void (*orig_interned_strings_restore)(void);
     345             : 
     346             : /* O+ disables creation of interned strings by regular PHP compiler, instead,
     347             :  * it creates interned strings in shared memory when saves a script.
     348             :  * Such interned strings are shared across all PHP processes
     349             :  */
     350        6826 : static zend_string *accel_new_interned_string_for_php(zend_string *str)
     351             : {
     352        6826 :         return str;
     353             : }
     354             : 
     355         477 : static void accel_interned_strings_snapshot_for_php(void)
     356             : {
     357         477 : }
     358             : 
     359         477 : static void accel_interned_strings_restore_for_php(void)
     360             : {
     361         477 : }
     362             : 
     363             : #ifndef ZTS
     364           0 : static void accel_interned_strings_restore_state(void)
     365             : {
     366           0 :     uint idx = ZCSG(interned_strings).nNumUsed;
     367             :     uint nIndex;
     368             :     Bucket *p;
     369             : 
     370           0 :         memset(ZCSG(interned_strings_saved_top),
     371           0 :                         0, ZCSG(interned_strings_top) - ZCSG(interned_strings_saved_top));
     372           0 :         ZCSG(interned_strings_top) = ZCSG(interned_strings_saved_top);
     373           0 :     while (idx > 0) {
     374           0 :         idx--;
     375           0 :                 p = ZCSG(interned_strings).arData + idx;
     376           0 :                 if ((char*)p->key < ZCSG(interned_strings_top)) break;
     377           0 :                 ZCSG(interned_strings).nNumUsed--;
     378           0 :                 ZCSG(interned_strings).nNumOfElements--;
     379             : 
     380           0 :                 nIndex = p->h | ZCSG(interned_strings).nTableMask;
     381           0 :                 if (HT_HASH(&ZCSG(interned_strings), nIndex) == HT_IDX_TO_HASH(idx)) {
     382           0 :                         HT_HASH(&ZCSG(interned_strings), nIndex) = Z_NEXT(p->val);
     383             :                 } else {
     384           0 :                         uint32_t prev = HT_HASH(&ZCSG(interned_strings), nIndex);
     385           0 :                         while (Z_NEXT(HT_HASH_TO_BUCKET(&ZCSG(interned_strings), prev)->val) != idx) {
     386           0 :                                 prev = Z_NEXT(HT_HASH_TO_BUCKET(&ZCSG(interned_strings), prev)->val);
     387             :                         }
     388           0 :                         Z_NEXT(HT_HASH_TO_BUCKET(&ZCSG(interned_strings), prev)->val) = Z_NEXT(p->val);
     389             :                 }
     390             :         }
     391           0 : }
     392             : 
     393         475 : static void accel_interned_strings_save_state(void)
     394             : {
     395         475 :         ZCSG(interned_strings_saved_top) = ZCSG(interned_strings_top);
     396         475 : }
     397             : #endif
     398             : 
     399             : #ifndef ZTS
     400         154 : static zend_string *accel_find_interned_string(zend_string *str)
     401             : {
     402             : /* for now interned strings are supported only for non-ZTS build */
     403             :         zend_ulong h;
     404             :         uint nIndex;
     405             :         uint idx;
     406             :         Bucket *arData, *p;
     407             : 
     408         154 :         if (IS_ACCEL_INTERNED(str)) {
     409             :                 /* this is already an interned string */
     410           2 :                 return str;
     411             :         }
     412         152 :         if (!ZCG(counted)) {
     413           0 :                 if (accel_activate_add() == FAILURE) {
     414           0 :                         return str;
     415             :                 }
     416           0 :                 ZCG(counted) = 1;
     417             :         }
     418             : 
     419         152 :         h = zend_string_hash_val(str);
     420         152 :         nIndex = h | ZCSG(interned_strings).nTableMask;
     421             : 
     422             :         /* check for existing interned string */
     423         152 :         idx = HT_HASH(&ZCSG(interned_strings), nIndex);
     424         152 :         arData = ZCSG(interned_strings).arData;
     425         304 :         while (idx != HT_INVALID_IDX) {
     426           0 :                 p = HT_HASH_TO_BUCKET_EX(arData, idx);
     427           0 :                 if ((p->h == h) && (ZSTR_LEN(p->key) == ZSTR_LEN(str))) {
     428           0 :                         if (!memcmp(ZSTR_VAL(p->key), ZSTR_VAL(str), ZSTR_LEN(str))) {
     429           0 :                                 return p->key;
     430             :                         }
     431             :                 }
     432           0 :                 idx = Z_NEXT(p->val);
     433             :         }
     434             : 
     435         152 :         return NULL;
     436             : }
     437             : #endif
     438             : 
     439     5633817 : zend_string *accel_new_interned_string(zend_string *str)
     440             : {
     441             : /* for now interned strings are supported only for non-ZTS build */
     442             : #ifndef ZTS
     443             :         zend_ulong h;
     444             :         uint nIndex;
     445             :         uint idx;
     446             :         Bucket *p;
     447             : 
     448             : #ifdef HAVE_OPCACHE_FILE_CACHE
     449     5633817 :         if (ZCG(accel_directives).file_cache_only) {
     450           4 :                 return str;
     451             :         }
     452             : #endif
     453             : 
     454     5633813 :         if (IS_ACCEL_INTERNED(str)) {
     455             :                 /* this is already an interned string */
     456           0 :                 return str;
     457             :         }
     458             : 
     459     5633813 :         h = zend_string_hash_val(str);
     460     5633813 :         nIndex = h | ZCSG(interned_strings).nTableMask;
     461             : 
     462             :         /* check for existing interned string */
     463     5633813 :         idx = HT_HASH(&ZCSG(interned_strings), nIndex);
     464    11337542 :         while (idx != HT_INVALID_IDX) {
     465     3487613 :                 p = HT_HASH_TO_BUCKET(&ZCSG(interned_strings), idx);
     466     3487613 :                 if ((p->h == h) && (ZSTR_LEN(p->key) == ZSTR_LEN(str))) {
     467     3417697 :                         if (!memcmp(ZSTR_VAL(p->key), ZSTR_VAL(str), ZSTR_LEN(str))) {
     468             :                                 zend_string_release(str);
     469     3417697 :                                 return p->key;
     470             :                         }
     471             :                 }
     472       69916 :                 idx = Z_NEXT(p->val);
     473             :         }
     474             : 
     475     4432232 :         if (ZCSG(interned_strings_top) + ZEND_MM_ALIGNED_SIZE(_ZSTR_STRUCT_SIZE(ZSTR_LEN(str))) >=
     476     2216116 :             ZCSG(interned_strings_end)) {
     477             :             /* no memory, return the same non-interned string */
     478          12 :                 zend_accel_error(ACCEL_LOG_WARNING, "Interned string buffer overflow");
     479          12 :                 return str;
     480             :         }
     481             : 
     482             :         /* create new interning string in shared interned strings buffer */
     483             : 
     484     2216104 :         idx = ZCSG(interned_strings).nNumUsed++;
     485     2216104 :         ZCSG(interned_strings).nNumOfElements++;
     486     2216104 :         p = ZCSG(interned_strings).arData + idx;
     487     2216104 :         p->key = (zend_string*) ZCSG(interned_strings_top);
     488     2216104 :         ZCSG(interned_strings_top) += ZEND_MM_ALIGNED_SIZE(_ZSTR_STRUCT_SIZE(ZSTR_LEN(str)));
     489     2216104 :         p->h = h;
     490     2216104 :         GC_REFCOUNT(p->key) = 1;
     491             : #if 1
     492             :         /* optimized single assignment */
     493     2216104 :         GC_TYPE_INFO(p->key) = IS_STRING | ((IS_STR_INTERNED | IS_STR_PERMANENT) << 8);
     494             : #else
     495             :         GC_TYPE(p->key) = IS_STRING;
     496             :         GC_FLAGS(p->key) = IS_STR_INTERNED | IS_STR_PERMANENT;
     497             : #endif
     498     2216104 :         ZSTR_H(p->key) = ZSTR_H(str);
     499     2216104 :         ZSTR_LEN(p->key) = ZSTR_LEN(str);
     500     2216104 :         memcpy(ZSTR_VAL(p->key), ZSTR_VAL(str), ZSTR_LEN(str));
     501     2216104 :         ZVAL_INTERNED_STR(&p->val, p->key);
     502     2216104 :         Z_NEXT(p->val) = HT_HASH(&ZCSG(interned_strings), nIndex);
     503     2216104 :         HT_HASH(&ZCSG(interned_strings), nIndex) = HT_IDX_TO_HASH(idx);
     504             :         zend_string_release(str);
     505     2216104 :         return p->key;
     506             : #else
     507             :         return str;
     508             : #endif
     509             : }
     510             : 
     511             : #ifndef ZTS
     512             : /* Copy PHP interned strings from PHP process memory into the shared memory */
     513         475 : static void accel_use_shm_interned_strings(void)
     514             : {
     515             :         uint idx, j;
     516             :         Bucket *p, *q;
     517             : 
     518             :         /* empty string */
     519         475 :         CG(empty_string) = accel_new_interned_string(CG(empty_string));
     520      122075 :         for (j = 0; j < 256; j++) {
     521             :                 char s[2];
     522      121600 :                 s[0] = j;
     523      121600 :                 s[1] = 0;
     524      243200 :                 CG(one_char_string)[j] = accel_new_interned_string(zend_string_init(s, 1, 0));
     525             :         }
     526       14250 :         for (j = 0; j < CG(known_strings_count); j++) {
     527       13775 :                 CG(known_strings)[j] = accel_new_interned_string(CG(known_strings)[j]);
     528             :         }
     529             : 
     530             :         /* function table hash keys */
     531     1098746 :         for (idx = 0; idx < CG(function_table)->nNumUsed; idx++) {
     532     1098271 :                 p = CG(function_table)->arData + idx;
     533     2196542 :                 if (Z_TYPE(p->val) == IS_UNDEF) continue;
     534     1098271 :                 if (p->key) {
     535     1098271 :                         p->key = accel_new_interned_string(p->key);
     536             :                 }
     537     1098271 :                 if (Z_FUNC(p->val)->common.function_name) {
     538     1098271 :                         Z_FUNC(p->val)->common.function_name = accel_new_interned_string(Z_FUNC(p->val)->common.function_name);
     539             :                 }
     540             :         }
     541             : 
     542             :         /* class table hash keys, class names, properties, methods, constants, etc */
     543       93100 :         for (idx = 0; idx < CG(class_table)->nNumUsed; idx++) {
     544             :                 zend_class_entry *ce;
     545             : 
     546       92625 :                 p = CG(class_table)->arData + idx;
     547      185250 :                 if (Z_TYPE(p->val) == IS_UNDEF) continue;
     548       92625 :                 ce = (zend_class_entry*)Z_PTR(p->val);
     549             : 
     550       92625 :                 if (p->key) {
     551       92625 :                         p->key = accel_new_interned_string(p->key);
     552             :                 }
     553             : 
     554       92625 :                 if (ce->name) {
     555       92625 :                         ce->name = accel_new_interned_string(ce->name);
     556             :                 }
     557             : 
     558      228475 :                 for (j = 0; j < ce->properties_info.nNumUsed; j++) {
     559             :                         zend_property_info *info;
     560             : 
     561      135850 :                         q = ce->properties_info.arData + j;
     562      271700 :                         if (Z_TYPE(q->val) == IS_UNDEF) continue;
     563             : 
     564      135375 :                         info = (zend_property_info*)Z_PTR(q->val);
     565             : 
     566      135375 :                         if (q->key) {
     567      135375 :                                 q->key = accel_new_interned_string(q->key);
     568             :                         }
     569             : 
     570      135375 :                         if (info->name) {
     571      135375 :                                 info->name = accel_new_interned_string(info->name);
     572             :                         }
     573             :                 }
     574             : 
     575     1508125 :                 for (j = 0; j < ce->function_table.nNumUsed; j++) {
     576     1415500 :                         q = ce->function_table.arData + j;
     577     2831000 :                         if (Z_TYPE(q->val) == IS_UNDEF) continue;
     578     1415500 :                         if (q->key) {
     579     1415500 :                                 q->key = accel_new_interned_string(q->key);
     580             :                         }
     581     1415500 :                         if (Z_FUNC(q->val)->common.function_name) {
     582     1415500 :                                 Z_FUNC(q->val)->common.function_name = accel_new_interned_string(Z_FUNC(q->val)->common.function_name);
     583             :                         }
     584             :                 }
     585             : 
     586      656925 :                 for (j = 0; j < ce->constants_table.nNumUsed; j++) {
     587      564300 :                         q = ce->constants_table.arData + j;
     588     1128600 :                         if (!Z_TYPE(q->val) == IS_UNDEF) continue;
     589           0 :                         if (q->key) {
     590           0 :                                 q->key = accel_new_interned_string(q->key);
     591             :                         }
     592             :                 }
     593             :         }
     594             : 
     595             :         /* constant hash keys */
     596     1262550 :         for (idx = 0; idx < EG(zend_constants)->nNumUsed; idx++) {
     597     1262075 :                 p = EG(zend_constants)->arData + idx;
     598     2524150 :                 if (!Z_TYPE(p->val) == IS_UNDEF) continue;
     599           0 :                 if (p->key) {
     600           0 :                         p->key = accel_new_interned_string(p->key);
     601             :                 }
     602             :         }
     603             : 
     604             :         /* auto globals hash keys and names */
     605        4750 :         for (idx = 0; idx < CG(auto_globals)->nNumUsed; idx++) {
     606             :                 zend_auto_global *auto_global;
     607             : 
     608        4275 :                 p = CG(auto_globals)->arData + idx;
     609        8550 :                 if (Z_TYPE(p->val) == IS_UNDEF) continue;
     610             : 
     611        4275 :                 auto_global = (zend_auto_global*)Z_PTR(p->val);;
     612             : 
     613        4275 :                 zend_string_addref(auto_global->name);
     614        4275 :                 auto_global->name = accel_new_interned_string(auto_global->name);
     615        4275 :                 if (p->key) {
     616        4275 :                         p->key = accel_new_interned_string(p->key);
     617             :                 }
     618             :         }
     619         475 : }
     620             : #endif
     621             : 
     622             : #ifndef ZEND_WIN32
     623           0 : static inline void kill_all_lockers(struct flock *mem_usage_check)
     624             : {
     625           0 :         int tries = 10;
     626             : 
     627             :         /* so that other process won't try to force while we are busy cleaning up */
     628           0 :         ZCSG(force_restart_time) = 0;
     629           0 :         while (mem_usage_check->l_pid > 0) {
     630           0 :                 while (tries--) {
     631           0 :                         zend_accel_error(ACCEL_LOG_WARNING, "Killed locker %d", mem_usage_check->l_pid);
     632           0 :                         if (kill(mem_usage_check->l_pid, SIGKILL)) {
     633           0 :                                 break;
     634             :                         }
     635             :                         /* give it a chance to die */
     636           0 :                         usleep(20000);
     637           0 :                         if (kill(mem_usage_check->l_pid, 0)) {
     638             :                                 /* can't kill it */
     639           0 :                                 break;
     640             :                         }
     641           0 :                         usleep(10000);
     642             :                 }
     643           0 :                 if (!tries) {
     644           0 :                         zend_accel_error(ACCEL_LOG_WARNING, "Can't kill %d after 10 tries!", mem_usage_check->l_pid);
     645           0 :                         ZCSG(force_restart_time) = time(NULL); /* restore forced restart request */
     646             :                 }
     647             : 
     648           0 :                 mem_usage_check->l_type = F_WRLCK;
     649           0 :                 mem_usage_check->l_whence = SEEK_SET;
     650           0 :                 mem_usage_check->l_start = 1;
     651           0 :                 mem_usage_check->l_len = 1;
     652           0 :                 mem_usage_check->l_pid = -1;
     653           0 :                 if (fcntl(lock_file, F_GETLK, mem_usage_check) == -1) {
     654           0 :                         zend_accel_error(ACCEL_LOG_DEBUG, "KLockers:  %s (%d)", strerror(errno), errno);
     655           0 :                         break;
     656             :                 }
     657             : 
     658           0 :                 if (mem_usage_check->l_type == F_UNLCK || mem_usage_check->l_pid <= 0) {
     659             :                         break;
     660             :                 }
     661             :         }
     662           0 : }
     663             : #endif
     664             : 
     665           0 : static inline int accel_is_inactive(void)
     666             : {
     667             : #ifdef ZEND_WIN32
     668             :         if (LOCKVAL(mem_usage) == 0) {
     669             :                 return SUCCESS;
     670             :         }
     671             : #else
     672           0 :         FLOCK_STRUCTURE(mem_usage_check, F_WRLCK, SEEK_SET, 1, 1);
     673             : 
     674           0 :         mem_usage_check.l_pid = -1;
     675           0 :         if (fcntl(lock_file, F_GETLK, &mem_usage_check) == -1) {
     676           0 :                 zend_accel_error(ACCEL_LOG_DEBUG, "UpdateC:  %s (%d)", strerror(errno), errno);
     677           0 :                 return FAILURE;
     678             :         }
     679           0 :         if (mem_usage_check.l_type == F_UNLCK) {
     680           0 :                 return SUCCESS;
     681             :         }
     682             : 
     683           0 :         if (ZCG(accel_directives).force_restart_timeout
     684           0 :                 && ZCSG(force_restart_time)
     685           0 :                 && time(NULL) >= ZCSG(force_restart_time)) {
     686           0 :                 zend_accel_error(ACCEL_LOG_WARNING, "Forced restart at %ld (after " ZEND_LONG_FMT " seconds), locked by %d", time(NULL), ZCG(accel_directives).force_restart_timeout, mem_usage_check.l_pid);
     687           0 :                 kill_all_lockers(&mem_usage_check);
     688             : 
     689           0 :                 return FAILURE; /* next request should be able to restart it */
     690             :         }
     691             : #endif
     692             : 
     693           0 :         return FAILURE;
     694             : }
     695             : 
     696           2 : static int zend_get_stream_timestamp(const char *filename, zend_stat_t *statbuf)
     697             : {
     698             :         php_stream_wrapper *wrapper;
     699             :         php_stream_statbuf stream_statbuf;
     700             :         int ret, er;
     701             : 
     702           2 :         if (!filename) {
     703           0 :                 return FAILURE;
     704             :         }
     705             : 
     706           2 :         wrapper = php_stream_locate_url_wrapper(filename, NULL, STREAM_LOCATE_WRAPPERS_ONLY);
     707           2 :         if (!wrapper) {
     708           2 :                 return FAILURE;
     709             :         }
     710           0 :         if (!wrapper->wops || !wrapper->wops->url_stat) {
     711           0 :                 statbuf->st_mtime = 1;
     712           0 :                 return SUCCESS; /* anything other than 0 is considered to be a valid timestamp */
     713             :         }
     714             : 
     715           0 :         er = EG(error_reporting);
     716           0 :         EG(error_reporting) = 0;
     717           0 :         zend_try {
     718           0 :                 ret = wrapper->wops->url_stat(wrapper, (char*)filename, PHP_STREAM_URL_STAT_QUIET, &stream_statbuf, NULL);
     719           0 :         } zend_catch {
     720           0 :                 ret = -1;
     721           0 :         } zend_end_try();
     722           0 :         EG(error_reporting) = er;
     723             : 
     724           0 :         if (ret != 0) {
     725           0 :                 return FAILURE;
     726             :         }
     727             : 
     728           0 :         *statbuf = stream_statbuf.sb;
     729           0 :         return SUCCESS;
     730             : }
     731             : 
     732             : #if ZEND_WIN32
     733             : static accel_time_t zend_get_file_handle_timestamp_win(zend_file_handle *file_handle, size_t *size)
     734             : {
     735             :         static unsigned __int64 utc_base = 0;
     736             :         static FILETIME utc_base_ft;
     737             :         WIN32_FILE_ATTRIBUTE_DATA fdata;
     738             : 
     739             :         if (!file_handle->opened_path) {
     740             :                 return 0;
     741             :         }
     742             : 
     743             :         if (!utc_base) {
     744             :                 SYSTEMTIME st;
     745             : 
     746             :                 st.wYear = 1970;
     747             :                 st.wMonth = 1;
     748             :                 st.wDay = 1;
     749             :                 st.wHour = 0;
     750             :                 st.wMinute = 0;
     751             :                 st.wSecond = 0;
     752             :                 st.wMilliseconds = 0;
     753             : 
     754             :                 SystemTimeToFileTime (&st, &utc_base_ft);
     755             :                 utc_base = (((unsigned __int64)utc_base_ft.dwHighDateTime) << 32) + utc_base_ft.dwLowDateTime;
     756             :     }
     757             : 
     758             :         if (file_handle->opened_path && GetFileAttributesEx(file_handle->opened_path->val, GetFileExInfoStandard, &fdata) != 0) {
     759             :                 unsigned __int64 ftime;
     760             : 
     761             :                 if (CompareFileTime (&fdata.ftLastWriteTime, &utc_base_ft) < 0) {
     762             :                         return 0;
     763             :                 }
     764             : 
     765             :                 ftime = (((unsigned __int64)fdata.ftLastWriteTime.dwHighDateTime) << 32) + fdata.ftLastWriteTime.dwLowDateTime - utc_base;
     766             :                 ftime /= 10000000L;
     767             : 
     768             :                 if (size) {
     769             :                         *size = (size_t)((((unsigned __int64)fdata.nFileSizeHigh) << 32) + (unsigned __int64)fdata.nFileSizeLow);
     770             :                 }
     771             :                 return (accel_time_t)ftime;
     772             :         }
     773             :         return 0;
     774             : }
     775             : #endif
     776             : 
     777         595 : accel_time_t zend_get_file_handle_timestamp(zend_file_handle *file_handle, size_t *size)
     778             : {
     779             :         zend_stat_t statbuf;
     780             : #ifdef ZEND_WIN32
     781             :         accel_time_t res;
     782             : #endif
     783             : 
     784         595 :         if (sapi_module.get_stat &&
     785           0 :             !EG(current_execute_data) &&
     786           0 :             file_handle->filename == SG(request_info).path_translated) {
     787             : 
     788           0 :                 zend_stat_t *tmpbuf = sapi_module.get_stat();
     789             : 
     790           0 :                 if (tmpbuf) {
     791           0 :                         if (size) {
     792           0 :                                 *size = tmpbuf->st_size;
     793             :                         }
     794           0 :                         return tmpbuf->st_mtime;
     795             :                 }
     796             :         }
     797             : 
     798             : #ifdef ZEND_WIN32
     799             :         res = zend_get_file_handle_timestamp_win(file_handle, size);
     800             :         if (res) {
     801             :                 return res;
     802             :         }
     803             : #endif
     804             : 
     805         595 :         switch (file_handle->type) {
     806             :                 case ZEND_HANDLE_FD:
     807           0 :                         if (zend_fstat(file_handle->handle.fd, &statbuf) == -1) {
     808           0 :                                 return 0;
     809             :                         }
     810           0 :                         break;
     811             :                 case ZEND_HANDLE_FP:
     812         102 :                         if (zend_fstat(fileno(file_handle->handle.fp), &statbuf) == -1) {
     813           0 :                                 if (zend_get_stream_timestamp(file_handle->filename, &statbuf) != SUCCESS) {
     814           0 :                                         return 0;
     815             :                                 }
     816             :                         }
     817         102 :                         break;
     818             :                 case ZEND_HANDLE_FILENAME:
     819             :                 case ZEND_HANDLE_MAPPED:
     820         458 :                         if (file_handle->opened_path) {
     821         457 :                                 char *file_path = ZSTR_VAL(file_handle->opened_path);
     822             : 
     823         457 :                                 if (is_stream_path(file_path)) {
     824           0 :                                         if (zend_get_stream_timestamp(file_path, &statbuf) == SUCCESS) {
     825           0 :                                                 break;
     826             :                                         }
     827             :                                 }
     828         457 :                                 if (VCWD_STAT(file_path, &statbuf) != -1) {
     829         456 :                                         break;
     830             :                                 }
     831             :                         }
     832             : 
     833           2 :                         if (zend_get_stream_timestamp(file_handle->filename, &statbuf) != SUCCESS) {
     834           2 :                                 return 0;
     835             :                         }
     836           0 :                         break;
     837             :                 case ZEND_HANDLE_STREAM:
     838             :                         {
     839          35 :                                 php_stream *stream = (php_stream *)file_handle->handle.stream.handle;
     840             :                                 php_stream_statbuf sb;
     841             :                                 int ret, er;
     842             : 
     843         105 :                                 if (!stream ||
     844          35 :                                     !stream->ops ||
     845          35 :                                     !stream->ops->stat) {
     846           0 :                                         return 0;
     847             :                                 }
     848             : 
     849          35 :                                 er = EG(error_reporting);
     850          35 :                                 EG(error_reporting) = 0;
     851          35 :                                 zend_try {
     852          35 :                                         ret = stream->ops->stat(stream, &sb);
     853           0 :                                 } zend_catch {
     854           0 :                                         ret = -1;
     855          35 :                                 } zend_end_try();
     856          35 :                                 EG(error_reporting) = er;
     857          35 :                                 if (ret != 0) {
     858           0 :                                         return 0;
     859             :                                 }
     860             : 
     861          35 :                                 statbuf = sb.sb;
     862             :                         }
     863          35 :                         break;
     864             : 
     865             :                 default:
     866           0 :                         return 0;
     867             :         }
     868             : 
     869         593 :         if (size) {
     870           0 :                 *size = statbuf.st_size;
     871             :         }
     872         593 :         return statbuf.st_mtime;
     873             : }
     874             : 
     875           2 : static inline int do_validate_timestamps(zend_persistent_script *persistent_script, zend_file_handle *file_handle)
     876             : {
     877             :         zend_file_handle ps_handle;
     878           2 :         zend_string *full_path_ptr = NULL;
     879             : 
     880             :         /** check that the persistent script is indeed the same file we cached
     881             :          * (if part of the path is a symlink than it possible that the user will change it)
     882             :          * See bug #15140
     883             :          */
     884           2 :         if (file_handle->opened_path) {
     885           0 :                 if (persistent_script->script.filename != file_handle->opened_path &&
     886           0 :                     (ZSTR_LEN(persistent_script->script.filename) != ZSTR_LEN(file_handle->opened_path) ||
     887           0 :                      memcmp(ZSTR_VAL(persistent_script->script.filename), ZSTR_VAL(file_handle->opened_path), ZSTR_LEN(file_handle->opened_path)) != 0)) {
     888           0 :                         return FAILURE;
     889             :                 }
     890             :         } else {
     891           2 :                 full_path_ptr = accelerator_orig_zend_resolve_path(file_handle->filename, strlen(file_handle->filename));
     892           5 :                 if (full_path_ptr &&
     893           1 :                     persistent_script->script.filename != full_path_ptr &&
     894           1 :                     (ZSTR_LEN(persistent_script->script.filename) != ZSTR_LEN(full_path_ptr) ||
     895           1 :                      memcmp(ZSTR_VAL(persistent_script->script.filename), ZSTR_VAL(full_path_ptr), ZSTR_LEN(full_path_ptr)) != 0)) {
     896             :                         zend_string_release(full_path_ptr);
     897           0 :                         return FAILURE;
     898             :                 }
     899           2 :                 file_handle->opened_path = full_path_ptr;
     900             :         }
     901             : 
     902           2 :         if (persistent_script->timestamp == 0) {
     903           0 :                 if (full_path_ptr) {
     904             :                         zend_string_release(full_path_ptr);
     905           0 :                         file_handle->opened_path = NULL;
     906             :                 }
     907           0 :                 return FAILURE;
     908             :         }
     909             : 
     910           2 :         if (zend_get_file_handle_timestamp(file_handle, NULL) == persistent_script->timestamp) {
     911           0 :                 if (full_path_ptr) {
     912             :                         zend_string_release(full_path_ptr);
     913           0 :                         file_handle->opened_path = NULL;
     914             :                 }
     915           0 :                 return SUCCESS;
     916             :         }
     917           2 :         if (full_path_ptr) {
     918             :                 zend_string_release(full_path_ptr);
     919           1 :                 file_handle->opened_path = NULL;
     920             :         }
     921             : 
     922           2 :         ps_handle.type = ZEND_HANDLE_FILENAME;
     923           2 :         ps_handle.filename = ZSTR_VAL(persistent_script->script.filename);
     924           2 :         ps_handle.opened_path = persistent_script->script.filename;
     925             : 
     926           2 :         if (zend_get_file_handle_timestamp(&ps_handle, NULL) == persistent_script->timestamp) {
     927           0 :                 return SUCCESS;
     928             :         }
     929             : 
     930           2 :         return FAILURE;
     931             : }
     932             : 
     933           6 : int validate_timestamp_and_record(zend_persistent_script *persistent_script, zend_file_handle *file_handle)
     934             : {
     935          10 :         if (ZCG(accel_directives).revalidate_freq &&
     936           4 :             persistent_script->dynamic_members.revalidate >= ZCG(request_time)) {
     937           4 :                 return SUCCESS;
     938           2 :         } else if (do_validate_timestamps(persistent_script, file_handle) == FAILURE) {
     939           2 :                 return FAILURE;
     940             :         } else {
     941           0 :                 persistent_script->dynamic_members.revalidate = ZCG(request_time) + ZCG(accel_directives).revalidate_freq;
     942           0 :                 return SUCCESS;
     943             :         }
     944             : }
     945             : 
     946             : /* Instead of resolving full real path name each time we need to identify file,
     947             :  * we create a key that consist from requested file name, current working
     948             :  * directory, current include_path, etc */
     949        1450 : char *accel_make_persistent_key(const char *path, int path_length, int *key_len)
     950             : {
     951             :         int key_length;
     952             : 
     953             :         /* CWD and include_path don't matter for absolute file names and streams */
     954        1450 :     if (IS_ABSOLUTE_PATH(path, path_length)) {
     955             :                 /* pass */
     956        1339 :                 ZCG(key_len) = 0;
     957         111 :     } else if (UNEXPECTED(is_stream_path(path))) {
     958          30 :                 if (!is_cacheable_stream_path(path)) {
     959           2 :                         return NULL;
     960             :                 }
     961             :                 /* pass */
     962          28 :                 ZCG(key_len) = 0;
     963          81 :     } else if (UNEXPECTED(!ZCG(accel_directives).use_cwd)) {
     964             :                 /* pass */
     965           0 :                 ZCG(key_len) = 0;
     966             :     } else {
     967          81 :                 const char *include_path = NULL, *cwd = NULL;
     968          81 :                 int include_path_len = 0, cwd_len = 0;
     969          81 :                 zend_string *parent_script = NULL;
     970          81 :                 size_t parent_script_len = 0;
     971             : 
     972          81 :                 if (EXPECTED(ZCG(cwd_key_len))) {
     973           4 :                         cwd = ZCG(cwd_key);
     974           4 :                         cwd_len = ZCG(cwd_key_len);
     975             :                 } else {
     976          77 :                         zend_string *cwd_str = accel_getcwd();
     977             : 
     978          77 :                         if (UNEXPECTED(!cwd_str)) {
     979             :                                 /* we don't handle this well for now. */
     980           0 :                                 zend_accel_error(ACCEL_LOG_INFO, "getcwd() failed for '%s' (%d), please try to set opcache.use_cwd to 0 in ini file", path, errno);
     981           0 :                                 return NULL;
     982             :                         }
     983          77 :                         cwd = ZSTR_VAL(cwd_str);
     984          77 :                         cwd_len = ZSTR_LEN(cwd_str);
     985             : #ifndef ZTS
     986          77 :                         if (ZCG(cwd_check)) {
     987          77 :                                 ZCG(cwd_check) = 0;
     988          77 :                                 if ((ZCG(counted) || ZCSG(accelerator_enabled))) {
     989             : 
     990          77 :                                         zend_string *str = accel_find_interned_string(cwd_str);
     991          77 :                                         if (!str) {
     992          77 :                                                 HANDLE_BLOCK_INTERRUPTIONS();
     993          77 :                                                 SHM_UNPROTECT();
     994          77 :                                                 zend_shared_alloc_lock();
     995          77 :                                                 str = accel_new_interned_string(zend_string_copy(cwd_str));
     996          77 :                                                 if (str == cwd_str) {
     997             :                                                         zend_string_release(str);
     998           1 :                                                         str = NULL;
     999             :                                                 }
    1000          77 :                                                 zend_shared_alloc_unlock();
    1001          77 :                                                 SHM_PROTECT();
    1002          77 :                                                 HANDLE_UNBLOCK_INTERRUPTIONS();
    1003             :                                         }
    1004          77 :                                         if (str) {
    1005             :                                                 char buf[32];
    1006         152 :                                                 char *res = zend_print_long_to_buf(buf + sizeof(buf) - 1, ZSTR_VAL(str) - ZCSG(interned_strings_start));
    1007             : 
    1008          76 :                                                 cwd_len = ZCG(cwd_key_len) = buf + sizeof(buf) - 1 - res;
    1009          76 :                                                 cwd = ZCG(cwd_key);
    1010          76 :                                                 memcpy(ZCG(cwd_key), res, cwd_len + 1);
    1011             :                                         }
    1012             :                                 }
    1013             :                         }
    1014             : #endif
    1015             :                 }
    1016             : 
    1017          81 :                 if (EXPECTED(ZCG(include_path_key_len))) {
    1018           4 :                         include_path = ZCG(include_path_key);
    1019           4 :                         include_path_len = ZCG(include_path_key_len);
    1020          77 :                 } else if (!ZCG(include_path) || ZSTR_LEN(ZCG(include_path)) == 0) {
    1021           0 :                         include_path = "";
    1022           0 :                         include_path_len = 0;
    1023             :                 } else {
    1024          77 :                         include_path = ZSTR_VAL(ZCG(include_path));
    1025          77 :                         include_path_len = ZSTR_LEN(ZCG(include_path));
    1026             : 
    1027             : #ifndef ZTS
    1028          77 :                         if (ZCG(include_path_check)) {
    1029          77 :                                 ZCG(include_path_check) = 0;
    1030          77 :                                 if ((ZCG(counted) || ZCSG(accelerator_enabled))) {
    1031             : 
    1032          77 :                                         zend_string *str = accel_find_interned_string(ZCG(include_path));
    1033          77 :                                         if (!str) {
    1034          75 :                                                 HANDLE_BLOCK_INTERRUPTIONS();
    1035          75 :                                                 SHM_UNPROTECT();
    1036          75 :                                                 zend_shared_alloc_lock();
    1037         150 :                                                 str = accel_new_interned_string(zend_string_copy(ZCG(include_path)));
    1038          75 :                                                 if (str == ZCG(include_path)) {
    1039           1 :                                                         str = NULL;
    1040             :                                                 }
    1041          75 :                                                 zend_shared_alloc_unlock();
    1042          75 :                                                 SHM_PROTECT();
    1043          75 :                                                 HANDLE_UNBLOCK_INTERRUPTIONS();
    1044             :                                         }
    1045          77 :                                         if (str) {
    1046             :                                                 char buf[32];
    1047         152 :                                                 char *res = zend_print_long_to_buf(buf + sizeof(buf) - 1, ZSTR_VAL(str) - ZCSG(interned_strings_start));
    1048             : 
    1049          76 :                                                 include_path_len = ZCG(include_path_key_len) = buf + sizeof(buf) - 1 - res;
    1050          76 :                                                 include_path = ZCG(include_path_key);
    1051          76 :                                                 memcpy(ZCG(include_path_key), res, include_path_len + 1);
    1052             :                                         }
    1053             :                                 }
    1054             :                         }
    1055             : #endif
    1056             :                 }
    1057             : 
    1058             :                 /* Calculate key length */
    1059          81 :                 if (UNEXPECTED((size_t)(cwd_len + path_length + include_path_len + 2) >= sizeof(ZCG(key)))) {
    1060           0 :                         return NULL;
    1061             :                 }
    1062             : 
    1063             :                 /* Generate key
    1064             :                  * Note - the include_path must be the last element in the key,
    1065             :                  * since in itself, it may include colons (which we use to separate
    1066             :                  * different components of the key)
    1067             :                  */
    1068          81 :                 memcpy(ZCG(key), path, path_length);
    1069          81 :                 ZCG(key)[path_length] = ':';
    1070          81 :                 key_length = path_length + 1;
    1071          81 :                 memcpy(ZCG(key) + key_length, cwd, cwd_len);
    1072          81 :                 key_length += cwd_len;
    1073             : 
    1074          81 :                 if (include_path_len) {
    1075          81 :                         ZCG(key)[key_length] = ':';
    1076          81 :                         key_length += 1;
    1077          81 :                         memcpy(ZCG(key) + key_length, include_path, include_path_len);
    1078          81 :                         key_length += include_path_len;
    1079             :                 }
    1080             : 
    1081             :                 /* Here we add to the key the parent script directory,
    1082             :                  * since fopen_wrappers from version 4.0.7 use current script's path
    1083             :                  * in include path too.
    1084             :                  */
    1085         243 :                 if (EXPECTED(EG(current_execute_data)) &&
    1086         162 :                     EXPECTED((parent_script = zend_get_executed_filename_ex()) != NULL)) {
    1087             : 
    1088          81 :                         parent_script_len = ZSTR_LEN(parent_script);
    1089        1576 :                         while ((--parent_script_len > 0) && !IS_SLASH(ZSTR_VAL(parent_script)[parent_script_len]));
    1090             : 
    1091          81 :                         if (UNEXPECTED((size_t)(key_length + parent_script_len + 1) >= sizeof(ZCG(key)))) {
    1092           0 :                                 return NULL;
    1093             :                         }
    1094          81 :                         ZCG(key)[key_length] = ':';
    1095          81 :                         key_length += 1;
    1096          81 :                         memcpy(ZCG(key) + key_length, ZSTR_VAL(parent_script), parent_script_len);
    1097          81 :                         key_length += parent_script_len;
    1098             :                 }
    1099          81 :                 ZCG(key)[key_length] = '\0';
    1100          81 :                 *key_len = ZCG(key_len) = key_length;
    1101          81 :                 return ZCG(key);
    1102             :         }
    1103             : 
    1104             :         /* not use_cwd */
    1105        1367 :         *key_len = path_length;
    1106        1367 :         return (char*)path;
    1107             : }
    1108             : 
    1109           2 : int zend_accel_invalidate(const char *filename, int filename_len, zend_bool force)
    1110             : {
    1111             :         zend_string *realpath;
    1112             :         zend_persistent_script *persistent_script;
    1113             : 
    1114           2 :         if (!ZCG(enabled) || !accel_startup_ok || !ZCSG(accelerator_enabled) || accelerator_shm_read_lock() != SUCCESS) {
    1115           0 :                 return FAILURE;
    1116             :         }
    1117             : 
    1118           2 :         realpath = accelerator_orig_zend_resolve_path(filename, filename_len);
    1119             : 
    1120           2 :         if (!realpath) {
    1121           1 :                 return FAILURE;
    1122             :         }
    1123             : 
    1124             : #ifdef HAVE_OPCACHE_FILE_CACHE
    1125           1 :         if (ZCG(accel_directives).file_cache) {
    1126           0 :                 zend_file_cache_invalidate(realpath);
    1127             :         }
    1128             : #endif
    1129             : 
    1130           1 :         persistent_script = zend_accel_hash_find(&ZCSG(hash), realpath);
    1131           1 :         if (persistent_script && !persistent_script->corrupted) {
    1132             :                 zend_file_handle file_handle;
    1133             : 
    1134           1 :                 file_handle.type = ZEND_HANDLE_FILENAME;
    1135           1 :                 file_handle.filename = ZSTR_VAL(realpath);
    1136           1 :                 file_handle.opened_path = realpath;
    1137             : 
    1138           1 :                 if (force ||
    1139           0 :                         !ZCG(accel_directives).validate_timestamps ||
    1140           0 :                         do_validate_timestamps(persistent_script, &file_handle) == FAILURE) {
    1141           1 :                         HANDLE_BLOCK_INTERRUPTIONS();
    1142           1 :                         SHM_UNPROTECT();
    1143           1 :                         zend_shared_alloc_lock();
    1144           1 :                         if (!persistent_script->corrupted) {
    1145           1 :                                 persistent_script->corrupted = 1;
    1146           1 :                                 persistent_script->timestamp = 0;
    1147           1 :                                 ZSMMG(wasted_shared_memory) += persistent_script->dynamic_members.memory_consumption;
    1148           1 :                                 if (ZSMMG(memory_exhausted)) {
    1149             :                                         zend_accel_restart_reason reason =
    1150           0 :                                                 zend_accel_hash_is_full(&ZCSG(hash)) ? ACCEL_RESTART_HASH : ACCEL_RESTART_OOM;
    1151           0 :                                         zend_accel_schedule_restart_if_necessary(reason);
    1152             :                                 }
    1153             :                         }
    1154           1 :                         zend_shared_alloc_unlock();
    1155           1 :                         SHM_PROTECT();
    1156           1 :                         HANDLE_UNBLOCK_INTERRUPTIONS();
    1157             :                 }
    1158             :         }
    1159             : 
    1160           1 :         accelerator_shm_read_unlock();
    1161             :         zend_string_release(realpath);
    1162             : 
    1163           1 :         return SUCCESS;
    1164             : }
    1165             : 
    1166             : /* Adds another key for existing cached script */
    1167           0 : static void zend_accel_add_key(char *key, unsigned int key_length, zend_accel_hash_entry *bucket)
    1168             : {
    1169           0 :         if (!zend_accel_hash_str_find(&ZCSG(hash), key, key_length)) {
    1170           0 :                 if (zend_accel_hash_is_full(&ZCSG(hash))) {
    1171           0 :                         zend_accel_error(ACCEL_LOG_DEBUG, "No more entries in hash table!");
    1172           0 :                         ZSMMG(memory_exhausted) = 1;
    1173           0 :                         zend_accel_schedule_restart_if_necessary(ACCEL_RESTART_HASH);
    1174             :                 } else {
    1175           0 :                         char *new_key = zend_shared_alloc(key_length + 1);
    1176           0 :                         if (new_key) {
    1177           0 :                                 memcpy(new_key, key, key_length + 1);
    1178           0 :                                 if (zend_accel_hash_update(&ZCSG(hash), new_key, key_length, 1, bucket)) {
    1179           0 :                                         zend_accel_error(ACCEL_LOG_INFO, "Added key '%s'", new_key);
    1180             :                                 }
    1181             :                         } else {
    1182           0 :                                 zend_accel_schedule_restart_if_necessary(ACCEL_RESTART_OOM);
    1183             :                         }
    1184             :                 }
    1185             :         }
    1186           0 : }
    1187             : 
    1188             : #ifdef HAVE_OPCACHE_FILE_CACHE
    1189           1 : static zend_persistent_script *cache_script_in_file_cache(zend_persistent_script *new_persistent_script, int *from_shared_memory)
    1190             : {
    1191             :         uint memory_used;
    1192             : 
    1193             :         /* Check if script may be stored in shared memory */
    1194           1 :         if (!zend_accel_script_persistable(new_persistent_script)) {
    1195           0 :                 return new_persistent_script;
    1196             :         }
    1197             : 
    1198           1 :         if (!zend_optimize_script(&new_persistent_script->script, ZCG(accel_directives).optimization_level, ZCG(accel_directives).opt_debug_level)) {
    1199           0 :                 return new_persistent_script;
    1200             :         }
    1201             : 
    1202           1 :         zend_shared_alloc_init_xlat_table();
    1203             : 
    1204             :         /* Calculate the required memory size */
    1205           1 :         memory_used = zend_accel_script_persist_calc(new_persistent_script, NULL, 0);
    1206             : 
    1207             :         /* Allocate memory block */
    1208             : #ifdef __SSE2__
    1209             :         /* Align to 64-byte boundary */
    1210           2 :         ZCG(mem) = zend_arena_alloc(&CG(arena), memory_used + 64);
    1211           1 :         ZCG(mem) = (void*)(((zend_uintptr_t)ZCG(mem) + 63L) & ~63L);
    1212             : #else
    1213             :         ZCG(mem) = zend_arena_alloc(&CG(arena), memory_used);
    1214             : #endif
    1215             : 
    1216             :         /* Copy into shared memory */
    1217           1 :         new_persistent_script = zend_accel_script_persist(new_persistent_script, NULL, 0);
    1218             : 
    1219           1 :         zend_shared_alloc_destroy_xlat_table();
    1220             : 
    1221           1 :         new_persistent_script->is_phar =
    1222           2 :                 new_persistent_script->script.filename &&
    1223           1 :                 strstr(ZSTR_VAL(new_persistent_script->script.filename), ".phar") &&
    1224           0 :                 !strstr(ZSTR_VAL(new_persistent_script->script.filename), "://");
    1225             : 
    1226             :         /* Consistency check */
    1227           1 :         if ((char*)new_persistent_script->mem + new_persistent_script->size != (char*)ZCG(mem)) {
    1228           0 :                 zend_accel_error(
    1229           0 :                         ((char*)new_persistent_script->mem + new_persistent_script->size < (char*)ZCG(mem)) ? ACCEL_LOG_ERROR : ACCEL_LOG_WARNING,
    1230             :                         "Internal error: wrong size calculation: %s start=" ZEND_ADDR_FMT ", end=" ZEND_ADDR_FMT ", real=" ZEND_ADDR_FMT "\n",
    1231           0 :                         ZSTR_VAL(new_persistent_script->script.filename),
    1232             :                         (size_t)new_persistent_script->mem,
    1233           0 :                         (size_t)((char *)new_persistent_script->mem + new_persistent_script->size),
    1234           0 :                         (size_t)ZCG(mem));
    1235             :         }
    1236             : 
    1237           1 :         new_persistent_script->dynamic_members.checksum = zend_accel_script_checksum(new_persistent_script);
    1238             : 
    1239           1 :         zend_file_cache_script_store(new_persistent_script, 0);
    1240             : 
    1241           1 :         *from_shared_memory = 1;
    1242           1 :         return new_persistent_script;
    1243             : }
    1244             : #endif
    1245             : 
    1246         587 : static zend_persistent_script *cache_script_in_shared_memory(zend_persistent_script *new_persistent_script, char *key, unsigned int key_length, int *from_shared_memory)
    1247             : {
    1248             :         zend_accel_hash_entry *bucket;
    1249             :         uint memory_used;
    1250             : 
    1251             :         /* Check if script may be stored in shared memory */
    1252         587 :         if (!zend_accel_script_persistable(new_persistent_script)) {
    1253           0 :                 return new_persistent_script;
    1254             :         }
    1255             : 
    1256         587 :         if (!zend_optimize_script(&new_persistent_script->script, ZCG(accel_directives).optimization_level, ZCG(accel_directives).opt_debug_level)) {
    1257           0 :                 return new_persistent_script;
    1258             :         }
    1259             : 
    1260             :         /* exclusive lock */
    1261         587 :         zend_shared_alloc_lock();
    1262             : 
    1263         587 :         if (zend_accel_hash_is_full(&ZCSG(hash))) {
    1264           0 :                 zend_accel_error(ACCEL_LOG_DEBUG, "No more entries in hash table!");
    1265           0 :                 ZSMMG(memory_exhausted) = 1;
    1266           0 :                 zend_accel_schedule_restart_if_necessary(ACCEL_RESTART_HASH);
    1267           0 :                 zend_shared_alloc_unlock();
    1268           0 :                 return new_persistent_script;
    1269             :         }
    1270             : 
    1271             :         /* Check if we still need to put the file into the cache (may be it was
    1272             :          * already stored by another process. This final check is done under
    1273             :          * exclusive lock) */
    1274         587 :         bucket = zend_accel_hash_find_entry(&ZCSG(hash), new_persistent_script->script.filename);
    1275         587 :         if (bucket) {
    1276           2 :                 zend_persistent_script *existing_persistent_script = (zend_persistent_script *)bucket->data;
    1277             : 
    1278           2 :                 if (!existing_persistent_script->corrupted) {
    1279           0 :                         if (key &&
    1280           0 :                             (!ZCG(accel_directives).validate_timestamps ||
    1281           0 :                              (new_persistent_script->timestamp == existing_persistent_script->timestamp))) {
    1282           0 :                                 zend_accel_add_key(key, key_length, bucket);
    1283             :                         }
    1284           0 :                         zend_shared_alloc_unlock();
    1285           0 :                         return new_persistent_script;
    1286             :                 }
    1287             :         }
    1288             : 
    1289             : 
    1290         587 :         zend_shared_alloc_init_xlat_table();
    1291             : 
    1292             :         /* Calculate the required memory size */
    1293         587 :         memory_used = zend_accel_script_persist_calc(new_persistent_script, key, key_length);
    1294             : 
    1295             :         /* Allocate shared memory */
    1296             : #ifdef __SSE2__
    1297             :         /* Align to 64-byte boundary */
    1298         587 :         ZCG(mem) = zend_shared_alloc(memory_used + 64);
    1299         587 :         ZCG(mem) = (void*)(((zend_uintptr_t)ZCG(mem) + 63L) & ~63L);
    1300             : #else
    1301             :         ZCG(mem) = zend_shared_alloc(memory_used);
    1302             : #endif
    1303         587 :         if (!ZCG(mem)) {
    1304           0 :                 zend_shared_alloc_destroy_xlat_table();
    1305           0 :                 zend_accel_schedule_restart_if_necessary(ACCEL_RESTART_OOM);
    1306           0 :                 zend_shared_alloc_unlock();
    1307           0 :                 return new_persistent_script;
    1308             :         }
    1309             : 
    1310             :         /* Copy into shared memory */
    1311         587 :         new_persistent_script = zend_accel_script_persist(new_persistent_script, &key, key_length);
    1312             : 
    1313         587 :         zend_shared_alloc_destroy_xlat_table();
    1314             : 
    1315         587 :         new_persistent_script->is_phar =
    1316        1253 :                 new_persistent_script->script.filename &&
    1317         587 :                 strstr(ZSTR_VAL(new_persistent_script->script.filename), ".phar") &&
    1318          79 :                 !strstr(ZSTR_VAL(new_persistent_script->script.filename), "://");
    1319             : 
    1320             :         /* Consistency check */
    1321         587 :         if ((char*)new_persistent_script->mem + new_persistent_script->size != (char*)ZCG(mem)) {
    1322           0 :                 zend_accel_error(
    1323           0 :                         ((char*)new_persistent_script->mem + new_persistent_script->size < (char*)ZCG(mem)) ? ACCEL_LOG_ERROR : ACCEL_LOG_WARNING,
    1324             :                         "Internal error: wrong size calculation: %s start=" ZEND_ADDR_FMT ", end=" ZEND_ADDR_FMT ", real=" ZEND_ADDR_FMT "\n",
    1325           0 :                         ZSTR_VAL(new_persistent_script->script.filename),
    1326             :                         (size_t)new_persistent_script->mem,
    1327           0 :                         (size_t)((char *)new_persistent_script->mem + new_persistent_script->size),
    1328           0 :                         (size_t)ZCG(mem));
    1329             :         }
    1330             : 
    1331         587 :         new_persistent_script->dynamic_members.checksum = zend_accel_script_checksum(new_persistent_script);
    1332             : 
    1333             :         /* store script structure in the hash table */
    1334         587 :         bucket = zend_accel_hash_update(&ZCSG(hash), ZSTR_VAL(new_persistent_script->script.filename), ZSTR_LEN(new_persistent_script->script.filename), 0, new_persistent_script);
    1335         587 :         if (bucket) {
    1336         587 :                 zend_accel_error(ACCEL_LOG_INFO, "Cached script '%s'", ZSTR_VAL(new_persistent_script->script.filename));
    1337        2257 :                 if (key &&
    1338             :                     /* key may contain non-persistent PHAR aliases (see issues #115 and #149) */
    1339         583 :                     memcmp(key, "phar://", sizeof("phar://") - 1) != 0 &&
    1340         556 :                     (ZSTR_LEN(new_persistent_script->script.filename) != key_length ||
    1341         531 :                      memcmp(ZSTR_VAL(new_persistent_script->script.filename), key, key_length) != 0)) {
    1342             :                         /* link key to the same persistent script in hash table */
    1343          25 :                         if (zend_accel_hash_update(&ZCSG(hash), key, key_length, 1, bucket)) {
    1344          25 :                                 zend_accel_error(ACCEL_LOG_INFO, "Added key '%s'", key);
    1345             :                         } else {
    1346           0 :                                 zend_accel_error(ACCEL_LOG_DEBUG, "No more entries in hash table!");
    1347           0 :                                 ZSMMG(memory_exhausted) = 1;
    1348           0 :                                 zend_accel_schedule_restart_if_necessary(ACCEL_RESTART_HASH);
    1349             :                         }
    1350             :                 }
    1351             :         }
    1352             : 
    1353         587 :         new_persistent_script->dynamic_members.memory_consumption = ZEND_ALIGNED_SIZE(new_persistent_script->size);
    1354             : 
    1355         587 :         zend_shared_alloc_unlock();
    1356             : 
    1357             : #ifdef HAVE_OPCACHE_FILE_CACHE
    1358         587 :         if (ZCG(accel_directives).file_cache) {
    1359           0 :                 SHM_PROTECT();
    1360           0 :                 zend_file_cache_script_store(new_persistent_script, 1);
    1361           0 :                 SHM_UNPROTECT();
    1362             :         }
    1363             : #endif
    1364             : 
    1365         587 :         *from_shared_memory = 1;
    1366         587 :         return new_persistent_script;
    1367             : }
    1368             : 
    1369             : static const struct jit_auto_global_info
    1370             : {
    1371             :     const char *name;
    1372             :     size_t len;
    1373             : } jit_auto_globals_info[] = {
    1374             :     { "_SERVER",  sizeof("_SERVER")-1},
    1375             :     { "_ENV",     sizeof("_ENV")-1},
    1376             :     { "_REQUEST", sizeof("_REQUEST")-1},
    1377             :     { "GLOBALS",  sizeof("GLOBALS")-1},
    1378             : };
    1379             : 
    1380             : static zend_string *jit_auto_globals_str[4];
    1381             : 
    1382         588 : static int zend_accel_get_auto_globals(void)
    1383             : {
    1384         588 :         int i, ag_size = (sizeof(jit_auto_globals_info) / sizeof(jit_auto_globals_info[0]));
    1385         588 :         int n = 1;
    1386         588 :         int mask = 0;
    1387             : 
    1388        2940 :         for (i = 0; i < ag_size ; i++) {
    1389        2352 :                 if (zend_hash_exists(&EG(symbol_table), jit_auto_globals_str[i])) {
    1390         403 :                         mask |= n;
    1391             :                 }
    1392        2352 :                 n += n;
    1393             :         }
    1394         588 :         return mask;
    1395             : }
    1396             : 
    1397           0 : static int zend_accel_get_auto_globals_no_jit(void)
    1398             : {
    1399           0 :         if (zend_hash_exists(&EG(symbol_table), jit_auto_globals_str[3])) {
    1400           0 :                 return 8;
    1401             :         }
    1402           0 :         return 0;
    1403             : }
    1404             : 
    1405         289 : static void zend_accel_set_auto_globals(int mask)
    1406             : {
    1407         289 :         int i, ag_size = (sizeof(jit_auto_globals_info) / sizeof(jit_auto_globals_info[0]));
    1408         289 :         int n = 1;
    1409             : 
    1410        1445 :         for (i = 0; i < ag_size ; i++) {
    1411        1156 :                 if ((mask & n) && !(ZCG(auto_globals_mask) & n)) {
    1412         292 :                         ZCG(auto_globals_mask) |= n;
    1413         292 :                         zend_is_auto_global(jit_auto_globals_str[i]);
    1414             :                 }
    1415        1156 :                 n += n;
    1416             :         }
    1417         289 : }
    1418             : 
    1419         478 : static void zend_accel_init_auto_globals(void)
    1420             : {
    1421         478 :         int i, ag_size = (sizeof(jit_auto_globals_info) / sizeof(jit_auto_globals_info[0]));
    1422             : 
    1423        2390 :         for (i = 0; i < ag_size ; i++) {
    1424        3824 :                 jit_auto_globals_str[i] = zend_string_init(jit_auto_globals_info[i].name, jit_auto_globals_info[i].len, 1);
    1425        1912 :                 zend_string_hash_val(jit_auto_globals_str[i]);
    1426        1912 :                 jit_auto_globals_str[i] = accel_new_interned_string(jit_auto_globals_str[i]);
    1427             :         }
    1428         478 : }
    1429             : 
    1430         596 : static zend_persistent_script *opcache_compile_file(zend_file_handle *file_handle, int type, char *key, zend_op_array **op_array_p)
    1431             : {
    1432             :         zend_persistent_script *new_persistent_script;
    1433             :         zend_op_array *orig_active_op_array;
    1434             :         HashTable *orig_function_table, *orig_class_table;
    1435             :         zval orig_user_error_handler;
    1436             :         zend_op_array *op_array;
    1437         596 :         int do_bailout = 0;
    1438         596 :         accel_time_t timestamp = 0;
    1439         596 :         uint32_t orig_compiler_options = 0;
    1440             : 
    1441             :     /* Try to open file */
    1442         596 :     if (file_handle->type == ZEND_HANDLE_FILENAME) {
    1443           3 :         if (accelerator_orig_zend_stream_open_function(file_handle->filename, file_handle) != SUCCESS) {
    1444           1 :                         *op_array_p = NULL;
    1445           1 :                         if (type == ZEND_REQUIRE) {
    1446           0 :                                 zend_message_dispatcher(ZMSG_FAILED_REQUIRE_FOPEN, file_handle->filename);
    1447           0 :                                 zend_bailout();
    1448             :                         } else {
    1449           1 :                                 zend_message_dispatcher(ZMSG_FAILED_INCLUDE_FOPEN, file_handle->filename);
    1450             :                         }
    1451           1 :                         return NULL;
    1452             :         }
    1453             :     }
    1454             : 
    1455             :         /* check blacklist right after ensuring that file was opened */
    1456         595 :         if (file_handle->opened_path && zend_accel_blacklist_is_blacklisted(&accel_blacklist, ZSTR_VAL(file_handle->opened_path))) {
    1457           1 :                 ZCSG(blacklist_misses)++;
    1458           1 :                 *op_array_p = accelerator_orig_compile_file(file_handle, type);
    1459           1 :                 return NULL;
    1460             :         }
    1461             : 
    1462         600 :         if (ZCG(accel_directives).validate_timestamps ||
    1463           3 :             ZCG(accel_directives).file_update_protection ||
    1464           3 :             ZCG(accel_directives).max_file_size > 0) {
    1465         591 :                 size_t size = 0;
    1466             : 
    1467             :                 /* Obtain the file timestamps, *before* actually compiling them,
    1468             :                  * otherwise we have a race-condition.
    1469             :                  */
    1470         591 :                 timestamp = zend_get_file_handle_timestamp(file_handle, ZCG(accel_directives).max_file_size > 0 ? &size : NULL);
    1471             : 
    1472             :                 /* If we can't obtain a timestamp (that means file is possibly socket)
    1473             :                  *  we won't cache it
    1474             :                  */
    1475         591 :                 if (timestamp == 0) {
    1476           0 :                         *op_array_p = accelerator_orig_compile_file(file_handle, type);
    1477           0 :                         return NULL;
    1478             :                 }
    1479             : 
    1480             :                 /* check if file is too new (may be it's not written completely yet) */
    1481         596 :                 if (ZCG(accel_directives).file_update_protection &&
    1482           5 :                     ((accel_time_t)(ZCG(request_time) - ZCG(accel_directives).file_update_protection) < timestamp)) {
    1483           3 :                         *op_array_p = accelerator_orig_compile_file(file_handle, type);
    1484           3 :                         return NULL;
    1485             :                 }
    1486             : 
    1487         588 :                 if (ZCG(accel_directives).max_file_size > 0 && size > (size_t)ZCG(accel_directives).max_file_size) {
    1488           0 :                         ZCSG(blacklist_misses)++;
    1489           0 :                         *op_array_p = accelerator_orig_compile_file(file_handle, type);
    1490           0 :                         return NULL;
    1491             :                 }
    1492             :         }
    1493             : 
    1494         591 :         new_persistent_script = create_persistent_script();
    1495             : 
    1496             :         /* Save the original values for the op_array, function table and class table */
    1497         591 :         orig_active_op_array = CG(active_op_array);
    1498         591 :         orig_function_table = CG(function_table);
    1499         591 :         orig_class_table = CG(class_table);
    1500         591 :         ZVAL_COPY_VALUE(&orig_user_error_handler, &EG(user_error_handler));
    1501             : 
    1502             :         /* Override them with ours */
    1503         591 :         CG(function_table) = &ZCG(function_table);
    1504         591 :         EG(class_table) = CG(class_table) = &new_persistent_script->script.class_table;
    1505         591 :         ZVAL_UNDEF(&EG(user_error_handler));
    1506             : 
    1507         591 :         zend_try {
    1508         591 :                 orig_compiler_options = CG(compiler_options);
    1509         591 :                 CG(compiler_options) |= ZEND_COMPILE_HANDLE_OP_ARRAY;
    1510         591 :                 CG(compiler_options) |= ZEND_COMPILE_IGNORE_INTERNAL_CLASSES;
    1511         591 :                 CG(compiler_options) |= ZEND_COMPILE_DELAYED_BINDING;
    1512         591 :                 CG(compiler_options) |= ZEND_COMPILE_NO_CONSTANT_SUBSTITUTION;
    1513         591 :                 op_array = *op_array_p = accelerator_orig_compile_file(file_handle, type);
    1514         589 :                 CG(compiler_options) = orig_compiler_options;
    1515           2 :         } zend_catch {
    1516           2 :                 op_array = NULL;
    1517           2 :                 do_bailout = 1;
    1518           2 :                 CG(compiler_options) = orig_compiler_options;
    1519         591 :         } zend_end_try();
    1520             : 
    1521             :         /* Restore originals */
    1522         591 :         CG(active_op_array) = orig_active_op_array;
    1523         591 :         CG(function_table) = orig_function_table;
    1524         591 :         EG(class_table) = CG(class_table) = orig_class_table;
    1525         591 :         EG(user_error_handler) = orig_user_error_handler;
    1526             : 
    1527         591 :         if (!op_array) {
    1528             :                 /* compilation failed */
    1529           3 :                 free_persistent_script(new_persistent_script, 1);
    1530           3 :                 zend_accel_free_user_functions(&ZCG(function_table));
    1531           3 :                 if (do_bailout) {
    1532           2 :                         zend_bailout();
    1533             :                 }
    1534           1 :                 return NULL;
    1535             :         }
    1536             : 
    1537             :         /* Build the persistent_script structure.
    1538             :            Here we aren't sure we would store it, but we will need it
    1539             :            further anyway.
    1540             :         */
    1541         588 :         zend_accel_move_user_functions(&ZCG(function_table), &new_persistent_script->script.function_table);
    1542         588 :         new_persistent_script->script.main_op_array = *op_array;
    1543             : 
    1544         588 :         efree(op_array); /* we have valid persistent_script, so it's safe to free op_array */
    1545             : 
    1546             :     /* Fill in the ping_auto_globals_mask for the new script. If jit for auto globals is enabled we
    1547             :        will have to ping the used auto global variables before execution */
    1548         588 :         if (PG(auto_globals_jit)) {
    1549         588 :                 new_persistent_script->ping_auto_globals_mask = zend_accel_get_auto_globals();
    1550             :         } else {
    1551           0 :                 new_persistent_script->ping_auto_globals_mask = zend_accel_get_auto_globals_no_jit();
    1552             :         }
    1553             : 
    1554         588 :         if (ZCG(accel_directives).validate_timestamps) {
    1555             :                 /* Obtain the file timestamps, *before* actually compiling them,
    1556             :                  * otherwise we have a race-condition.
    1557             :                  */
    1558         585 :                 new_persistent_script->timestamp = timestamp;
    1559         585 :                 new_persistent_script->dynamic_members.revalidate = ZCG(request_time) + ZCG(accel_directives).revalidate_freq;
    1560             :         }
    1561             : 
    1562         588 :         if (file_handle->opened_path) {
    1563        1176 :                 new_persistent_script->script.filename = zend_string_copy(file_handle->opened_path);
    1564             :         } else {
    1565           0 :                 new_persistent_script->script.filename = zend_string_init(file_handle->filename, strlen(file_handle->filename), 0);
    1566             :         }
    1567         588 :         zend_string_hash_val(new_persistent_script->script.filename);
    1568             : 
    1569             :         /* Now persistent_script structure is ready in process memory */
    1570         588 :         return new_persistent_script;
    1571             : }
    1572             : 
    1573             : #ifdef HAVE_OPCACHE_FILE_CACHE
    1574           1 : zend_op_array *file_cache_compile_file(zend_file_handle *file_handle, int type)
    1575             : {
    1576             :         zend_persistent_script *persistent_script;
    1577           1 :         zend_op_array *op_array = NULL;
    1578             :         int from_memory; /* if the script we've got is stored in SHM */
    1579             : 
    1580           1 :         if (is_stream_path(file_handle->filename) &&
    1581           0 :             !is_cacheable_stream_path(file_handle->filename)) {
    1582           0 :                 return accelerator_orig_compile_file(file_handle, type);
    1583             :         }
    1584             : 
    1585           1 :         if (!file_handle->opened_path) {
    1586           0 :                 if (file_handle->type == ZEND_HANDLE_FILENAME &&
    1587           0 :                     accelerator_orig_zend_stream_open_function(file_handle->filename, file_handle) == FAILURE) {
    1588           0 :                         if (type == ZEND_REQUIRE) {
    1589           0 :                                 zend_message_dispatcher(ZMSG_FAILED_REQUIRE_FOPEN, file_handle->filename);
    1590           0 :                                 zend_bailout();
    1591             :                         } else {
    1592           0 :                                 zend_message_dispatcher(ZMSG_FAILED_INCLUDE_FOPEN, file_handle->filename);
    1593             :                         }
    1594           0 :                         return NULL;
    1595             :             }
    1596             :         }
    1597             : 
    1598           1 :         HANDLE_BLOCK_INTERRUPTIONS();
    1599           1 :         SHM_UNPROTECT();
    1600           1 :         persistent_script = zend_file_cache_script_load(file_handle);
    1601           1 :         SHM_PROTECT();
    1602           1 :         HANDLE_UNBLOCK_INTERRUPTIONS();
    1603           1 :         if (persistent_script) {
    1604             :                 /* see bug #15471 (old BTS) */
    1605           0 :                 if (persistent_script->script.filename) {
    1606           0 :                         if (!EG(current_execute_data) || !EG(current_execute_data)->opline ||
    1607           0 :                             !EG(current_execute_data)->func ||
    1608           0 :                             !ZEND_USER_CODE(EG(current_execute_data)->func->common.type) ||
    1609           0 :                             EG(current_execute_data)->opline->opcode != ZEND_INCLUDE_OR_EVAL ||
    1610           0 :                             (EG(current_execute_data)->opline->extended_value != ZEND_INCLUDE_ONCE &&
    1611           0 :                              EG(current_execute_data)->opline->extended_value != ZEND_REQUIRE_ONCE)) {
    1612           0 :                                 if (zend_hash_add_empty_element(&EG(included_files), persistent_script->script.filename) != NULL) {
    1613             :                                         /* ext/phar has to load phar's metadata into memory */
    1614           0 :                                         if (persistent_script->is_phar) {
    1615             :                                                 php_stream_statbuf ssb;
    1616           0 :                                                 char *fname = emalloc(sizeof("phar://") + ZSTR_LEN(persistent_script->script.filename));
    1617             : 
    1618           0 :                                                 memcpy(fname, "phar://", sizeof("phar://") - 1);
    1619           0 :                                                 memcpy(fname + sizeof("phar://") - 1, ZSTR_VAL(persistent_script->script.filename), ZSTR_LEN(persistent_script->script.filename) + 1);
    1620           0 :                                                 php_stream_stat_path(fname, &ssb);
    1621           0 :                                                 efree(fname);
    1622             :                                         }
    1623             :                                 }
    1624             :                         }
    1625             :                 }
    1626           0 :                 zend_file_handle_dtor(file_handle);
    1627             : 
    1628           0 :             if (persistent_script->ping_auto_globals_mask) {
    1629           0 :                         zend_accel_set_auto_globals(persistent_script->ping_auto_globals_mask);
    1630             :                 }
    1631             : 
    1632           0 :                 return zend_accel_load_script(persistent_script, 1);
    1633             :         }
    1634             : 
    1635           1 :         persistent_script = opcache_compile_file(file_handle, type, NULL, &op_array);
    1636             : 
    1637           1 :         if (persistent_script) {
    1638           1 :                 from_memory = 0;
    1639           1 :                 persistent_script = cache_script_in_file_cache(persistent_script, &from_memory);
    1640           1 :                 return zend_accel_load_script(persistent_script, from_memory);
    1641             :         }
    1642             : 
    1643           0 :         return op_array;
    1644             : }
    1645             : #endif
    1646             : 
    1647             : /* zend_compile() replacement */
    1648         603 : zend_op_array *persistent_compile_file(zend_file_handle *file_handle, int type)
    1649             : {
    1650         603 :         zend_persistent_script *persistent_script = NULL;
    1651         603 :         char *key = NULL;
    1652             :         int key_length;
    1653             :         int from_shared_memory; /* if the script we've got is stored in SHM */
    1654             : 
    1655         603 :         if (!file_handle->filename || !ZCG(enabled) || !accel_startup_ok) {
    1656             :                 /* The Accelerator is disabled, act as if without the Accelerator */
    1657           0 :                 return accelerator_orig_compile_file(file_handle, type);
    1658             : #ifdef HAVE_OPCACHE_FILE_CACHE
    1659         603 :         } else if (ZCG(accel_directives).file_cache_only) {
    1660           1 :                 return file_cache_compile_file(file_handle, type);
    1661             : #endif
    1662        1204 :         } else if ((!ZCG(counted) && !ZCSG(accelerator_enabled)) ||
    1663         602 :                    (ZCSG(restart_in_progress) && accel_restart_is_active())) {
    1664             : #ifdef HAVE_OPCACHE_FILE_CACHE
    1665           0 :                 if (ZCG(accel_directives).file_cache) {
    1666           0 :                         return file_cache_compile_file(file_handle, type);
    1667             :                 }
    1668             : #endif
    1669           0 :                 return accelerator_orig_compile_file(file_handle, type);
    1670             :         }
    1671             : 
    1672             :         /* In case this callback is called from include_once, require_once or it's
    1673             :          * a main FastCGI request, the key must be already calculated, and cached
    1674             :          * persistent script already found */
    1675         602 :         if (ZCG(cache_persistent_script) &&
    1676           0 :             ((!EG(current_execute_data) &&
    1677           0 :               file_handle->filename == SG(request_info).path_translated &&
    1678           0 :               ZCG(cache_opline) == NULL) ||
    1679           0 :              (EG(current_execute_data) &&
    1680           0 :               EG(current_execute_data)->func &&
    1681           0 :               ZEND_USER_CODE(EG(current_execute_data)->func->common.type) &&
    1682           0 :               ZCG(cache_opline) == EG(current_execute_data)->opline))) {
    1683             : 
    1684           0 :                 persistent_script = ZCG(cache_persistent_script);
    1685           0 :                 if (ZCG(key_len)) {
    1686           0 :                         key = ZCG(key);
    1687           0 :                         key_length = ZCG(key_len);
    1688             :                 }
    1689             : 
    1690             :         } else {
    1691         602 :                 if (!ZCG(accel_directives).revalidate_path) {
    1692             :                         /* try to find cached script by key */
    1693         598 :                         key = accel_make_persistent_key(file_handle->filename, strlen(file_handle->filename), &key_length);
    1694         598 :                         if (!key) {
    1695           2 :                                 return accelerator_orig_compile_file(file_handle, type);
    1696             :                         }
    1697         596 :                         persistent_script = zend_accel_hash_str_find(&ZCSG(hash), key, key_length);
    1698             :                 }
    1699         600 :                 if (!persistent_script) {
    1700             :                         /* try to find cached script by full real path */
    1701             :                         zend_accel_hash_entry *bucket;
    1702             : 
    1703             :                         /* open file to resolve the path */
    1704         660 :                     if (file_handle->type == ZEND_HANDLE_FILENAME &&
    1705          66 :                         accelerator_orig_zend_stream_open_function(file_handle->filename, file_handle) == FAILURE) {
    1706           2 :                                 if (type == ZEND_REQUIRE) {
    1707           0 :                                         zend_message_dispatcher(ZMSG_FAILED_REQUIRE_FOPEN, file_handle->filename);
    1708           0 :                                         zend_bailout();
    1709             :                                 } else {
    1710           2 :                                         zend_message_dispatcher(ZMSG_FAILED_INCLUDE_FOPEN, file_handle->filename);
    1711             :                                 }
    1712           2 :                                 return NULL;
    1713             :                     }
    1714             : 
    1715         592 :                         if (file_handle->opened_path) {
    1716         592 :                                 bucket = zend_accel_hash_find_entry(&ZCSG(hash), file_handle->opened_path);
    1717             : 
    1718         592 :                                 if (bucket) {
    1719           0 :                                         persistent_script = (zend_persistent_script *)bucket->data;
    1720             : 
    1721           0 :                                         if (key && !persistent_script->corrupted) {
    1722           0 :                                                 HANDLE_BLOCK_INTERRUPTIONS();
    1723           0 :                                                 SHM_UNPROTECT();
    1724           0 :                                                 zend_shared_alloc_lock();
    1725           0 :                                                 zend_accel_add_key(key, key_length, bucket);
    1726           0 :                                                 zend_shared_alloc_unlock();
    1727           0 :                                                 SHM_PROTECT();
    1728           0 :                                                 HANDLE_UNBLOCK_INTERRUPTIONS();
    1729             :                                         }
    1730             :                                 }
    1731             :                         }
    1732             :                 }
    1733             :         }
    1734             : 
    1735             :         /* clear cache */
    1736         598 :         ZCG(cache_opline) = NULL;
    1737         598 :         ZCG(cache_persistent_script) = NULL;
    1738             : 
    1739         598 :         if (persistent_script && persistent_script->corrupted) {
    1740           1 :                 persistent_script = NULL;
    1741             :         }
    1742             : 
    1743             :         /* Make sure we only increase the currently running processes semaphore
    1744             :      * once each execution (this function can be called more than once on
    1745             :      * each execution)
    1746             :      */
    1747         598 :         if (!ZCG(counted)) {
    1748         476 :                 if (accel_activate_add() == FAILURE) {
    1749             : #ifdef HAVE_OPCACHE_FILE_CACHE
    1750           0 :                         if (ZCG(accel_directives).file_cache) {
    1751           0 :                                 return file_cache_compile_file(file_handle, type);
    1752             :                         }
    1753             : #endif
    1754           0 :                         return accelerator_orig_compile_file(file_handle, type);
    1755             :                 }
    1756         476 :                 ZCG(counted) = 1;
    1757             :         }
    1758             : 
    1759         598 :         HANDLE_BLOCK_INTERRUPTIONS();
    1760         598 :         SHM_UNPROTECT();
    1761             : 
    1762             :         /* If script is found then validate_timestamps if option is enabled */
    1763         598 :         if (persistent_script && ZCG(accel_directives).validate_timestamps) {
    1764           5 :                 if (validate_timestamp_and_record(persistent_script, file_handle) == FAILURE) {
    1765           2 :                         zend_shared_alloc_lock();
    1766           2 :                         if (!persistent_script->corrupted) {
    1767           2 :                                 persistent_script->corrupted = 1;
    1768           2 :                                 persistent_script->timestamp = 0;
    1769           2 :                                 ZSMMG(wasted_shared_memory) += persistent_script->dynamic_members.memory_consumption;
    1770           2 :                                 if (ZSMMG(memory_exhausted)) {
    1771             :                                         zend_accel_restart_reason reason =
    1772           0 :                                                 zend_accel_hash_is_full(&ZCSG(hash)) ? ACCEL_RESTART_HASH : ACCEL_RESTART_OOM;
    1773           0 :                                         zend_accel_schedule_restart_if_necessary(reason);
    1774             :                                 }
    1775             :                         }
    1776           2 :                         zend_shared_alloc_unlock();
    1777           2 :                         persistent_script = NULL;
    1778             :                 }
    1779             :         }
    1780             : 
    1781             :         /* if turned on - check the compiled script ADLER32 checksum */
    1782         601 :         if (persistent_script && ZCG(accel_directives).consistency_checks
    1783           3 :                 && persistent_script->dynamic_members.hits % ZCG(accel_directives).consistency_checks == 0) {
    1784             : 
    1785           0 :                 unsigned int checksum = zend_accel_script_checksum(persistent_script);
    1786           0 :                 if (checksum != persistent_script->dynamic_members.checksum ) {
    1787             :                         /* The checksum is wrong */
    1788           0 :                         zend_accel_error(ACCEL_LOG_INFO, "Checksum failed for '%s':  expected=0x%08x, found=0x%08x",
    1789           0 :                                                          ZSTR_VAL(persistent_script->script.filename), persistent_script->dynamic_members.checksum, checksum);
    1790           0 :                         zend_shared_alloc_lock();
    1791           0 :                         if (!persistent_script->corrupted) {
    1792           0 :                                 persistent_script->corrupted = 1;
    1793           0 :                                 persistent_script->timestamp = 0;
    1794           0 :                                 ZSMMG(wasted_shared_memory) += persistent_script->dynamic_members.memory_consumption;
    1795           0 :                                 if (ZSMMG(memory_exhausted)) {
    1796             :                                         zend_accel_restart_reason reason =
    1797           0 :                                                 zend_accel_hash_is_full(&ZCSG(hash)) ? ACCEL_RESTART_HASH : ACCEL_RESTART_OOM;
    1798           0 :                                         zend_accel_schedule_restart_if_necessary(reason);
    1799             :                                 }
    1800             :                         }
    1801           0 :                         zend_shared_alloc_unlock();
    1802           0 :                         persistent_script = NULL;
    1803             :                 }
    1804             :         }
    1805             : 
    1806             : #ifdef HAVE_OPCACHE_FILE_CACHE
    1807             :         /* Check the second level cache */
    1808         598 :         if (!persistent_script && ZCG(accel_directives).file_cache) {
    1809           0 :                 persistent_script = zend_file_cache_script_load(file_handle);
    1810             :         }
    1811             : #endif
    1812             : 
    1813             :         /* If script was not found or invalidated by validate_timestamps */
    1814         598 :         if (!persistent_script) {
    1815         595 :                 uint32_t old_const_num = zend_hash_next_free_element(EG(zend_constants));
    1816             :                 zend_op_array *op_array;
    1817             : 
    1818             :                 /* Cache miss.. */
    1819         595 :                 ZCSG(misses)++;
    1820             : 
    1821             :                 /* No memory left. Behave like without the Accelerator */
    1822         595 :                 if (ZSMMG(memory_exhausted) || ZCSG(restart_pending)) {
    1823           0 :                         SHM_PROTECT();
    1824           0 :                         HANDLE_UNBLOCK_INTERRUPTIONS();
    1825           0 :                         return accelerator_orig_compile_file(file_handle, type);
    1826             :                 }
    1827             : 
    1828             :                 /* Try and cache the script and assume that it is returned from_shared_memory.
    1829             :          * If it isn't compile_and_cache_file() changes the flag to 0
    1830             :          */
    1831         595 :         from_shared_memory = 0;
    1832         595 :                 persistent_script = opcache_compile_file(file_handle, type, key, &op_array);
    1833         593 :                 if (persistent_script) {
    1834         587 :                         persistent_script = cache_script_in_shared_memory(persistent_script, key, key ? key_length : 0, &from_shared_memory);
    1835             :                 }
    1836             : 
    1837             :                 /* Caching is disabled, returning op_array;
    1838             :                  * or something went wrong during compilation, returning NULL
    1839             :                  */
    1840         593 :                 if (!persistent_script) {
    1841           6 :                         SHM_PROTECT();
    1842           6 :                         HANDLE_UNBLOCK_INTERRUPTIONS();
    1843           6 :                         return op_array;
    1844             :                 }
    1845         587 :                 if (from_shared_memory) {
    1846             :                         /* Delete immutable arrays moved into SHM */
    1847         587 :                         uint32_t new_const_num = zend_hash_next_free_element(EG(zend_constants));
    1848        1174 :                         while (new_const_num > old_const_num) {
    1849           0 :                                 new_const_num--;
    1850           0 :                                 zend_hash_index_del(EG(zend_constants), new_const_num);
    1851             :                         }
    1852             :                 }
    1853             :         } else {
    1854             : 
    1855             : #if !ZEND_WIN32
    1856           3 :                 ZCSG(hits)++; /* TBFixed: may lose one hit */
    1857           3 :                 persistent_script->dynamic_members.hits++; /* see above */
    1858             : #else
    1859             : #ifdef _M_X64
    1860             :                 InterlockedIncrement64(&ZCSG(hits));
    1861             : #else
    1862             :                 InterlockedIncrement(&ZCSG(hits));
    1863             : #endif
    1864             :                 InterlockedIncrement64(&persistent_script->dynamic_members.hits);
    1865             : #endif
    1866             : 
    1867             :                 /* see bug #15471 (old BTS) */
    1868           3 :                 if (persistent_script->script.filename) {
    1869          18 :                         if (!EG(current_execute_data) || !EG(current_execute_data)->opline ||
    1870           3 :                             !EG(current_execute_data)->func ||
    1871           3 :                             !ZEND_USER_CODE(EG(current_execute_data)->func->common.type) ||
    1872           3 :                             EG(current_execute_data)->opline->opcode != ZEND_INCLUDE_OR_EVAL ||
    1873           3 :                             (EG(current_execute_data)->opline->extended_value != ZEND_INCLUDE_ONCE &&
    1874           3 :                              EG(current_execute_data)->opline->extended_value != ZEND_REQUIRE_ONCE)) {
    1875           3 :                                 if (zend_hash_add_empty_element(&EG(included_files), persistent_script->script.filename) != NULL) {
    1876             :                                         /* ext/phar has to load phar's metadata into memory */
    1877           0 :                                         if (persistent_script->is_phar) {
    1878             :                                                 php_stream_statbuf ssb;
    1879           0 :                                                 char *fname = emalloc(sizeof("phar://") + ZSTR_LEN(persistent_script->script.filename));
    1880             : 
    1881           0 :                                                 memcpy(fname, "phar://", sizeof("phar://") - 1);
    1882           0 :                                                 memcpy(fname + sizeof("phar://") - 1, ZSTR_VAL(persistent_script->script.filename), ZSTR_LEN(persistent_script->script.filename) + 1);
    1883           0 :                                                 php_stream_stat_path(fname, &ssb);
    1884           0 :                                                 efree(fname);
    1885             :                                         }
    1886             :                                 }
    1887             :                         }
    1888             :                 }
    1889           3 :                 zend_file_handle_dtor(file_handle);
    1890           3 :                 from_shared_memory = 1;
    1891             :         }
    1892             : 
    1893         590 :         persistent_script->dynamic_members.last_used = ZCG(request_time);
    1894             : 
    1895         590 :         SHM_PROTECT();
    1896         590 :         HANDLE_UNBLOCK_INTERRUPTIONS();
    1897             : 
    1898             :     /* Fetch jit auto globals used in the script before execution */
    1899         590 :     if (persistent_script->ping_auto_globals_mask) {
    1900         289 :                 zend_accel_set_auto_globals(persistent_script->ping_auto_globals_mask);
    1901             :         }
    1902             : 
    1903         590 :         return zend_accel_load_script(persistent_script, from_shared_memory);
    1904             : }
    1905             : 
    1906             : /* zend_stream_open_function() replacement for PHP 5.3 and above */
    1907         473 : static int persistent_stream_open_function(const char *filename, zend_file_handle *handle)
    1908             : {
    1909         473 :         if (ZCG(cache_persistent_script)) {
    1910             :                 /* check if callback is called from include_once or it's a main request */
    1911           0 :                 if ((!EG(current_execute_data) &&
    1912           0 :                      filename == SG(request_info).path_translated &&
    1913           0 :                      ZCG(cache_opline) == NULL) ||
    1914           0 :                     (EG(current_execute_data) &&
    1915           0 :                      EG(current_execute_data)->func &&
    1916           0 :                      ZEND_USER_CODE(EG(current_execute_data)->func->common.type) &&
    1917           0 :                      ZCG(cache_opline) == EG(current_execute_data)->opline)) {
    1918             : 
    1919             :                         /* we are in include_once or FastCGI request */
    1920           0 :                         handle->filename = (char*)filename;
    1921           0 :                         handle->free_filename = 0;
    1922           0 :                         handle->opened_path = zend_string_copy(ZCG(cache_persistent_script)->script.filename);
    1923           0 :                         handle->type = ZEND_HANDLE_FILENAME;
    1924           0 :                         return SUCCESS;
    1925             :                 }
    1926           0 :                 ZCG(cache_opline) = NULL;
    1927           0 :                 ZCG(cache_persistent_script) = NULL;
    1928             :         }
    1929         473 :         return accelerator_orig_zend_stream_open_function(filename, handle);
    1930             : }
    1931             : 
    1932             : /* zend_resolve_path() replacement for PHP 5.3 and above */
    1933         969 : static zend_string* persistent_zend_resolve_path(const char *filename, int filename_len)
    1934             : {
    1935        3653 :         if (ZCG(enabled) && accel_startup_ok &&
    1936        1715 :             (ZCG(counted) || ZCSG(accelerator_enabled)) &&
    1937         969 :             !ZCSG(restart_in_progress)) {
    1938             : 
    1939             :                 /* check if callback is called from include_once or it's a main request */
    1940        2800 :                 if ((!EG(current_execute_data) &&
    1941         780 :                      filename == SG(request_info).path_translated) ||
    1942         223 :                     (EG(current_execute_data) &&
    1943         189 :                      EG(current_execute_data)->func &&
    1944         189 :                      ZEND_USER_CODE(EG(current_execute_data)->func->common.type) &&
    1945         150 :                      EG(current_execute_data)->opline->opcode == ZEND_INCLUDE_OR_EVAL &&
    1946         150 :                      (EG(current_execute_data)->opline->extended_value == ZEND_INCLUDE_ONCE ||
    1947         150 :                       EG(current_execute_data)->opline->extended_value == ZEND_REQUIRE_ONCE))) {
    1948             : 
    1949             :                         /* we are in include_once or FastCGI request */
    1950             :                         zend_string *resolved_path;
    1951             :                         int key_length;
    1952         850 :                         char *key = NULL;
    1953             :                         
    1954         850 :                         if (!ZCG(accel_directives).revalidate_path) {
    1955             :                                 /* lookup by "not-real" path */
    1956         848 :                                 key = accel_make_persistent_key(filename, filename_len, &key_length);
    1957         848 :                                 if (key) {
    1958         848 :                                         zend_accel_hash_entry *bucket = zend_accel_hash_str_find_entry(&ZCSG(hash), key, key_length);
    1959         848 :                                         if (bucket != NULL) {
    1960           0 :                                                 zend_persistent_script *persistent_script = (zend_persistent_script *)bucket->data;
    1961           0 :                                                 if (!persistent_script->corrupted) {
    1962           0 :                                                         ZCG(cache_opline) = EG(current_execute_data) ? EG(current_execute_data)->opline : NULL;
    1963           0 :                                                         ZCG(cache_persistent_script) = persistent_script;
    1964           0 :                                                         return zend_string_copy(persistent_script->script.filename);
    1965             :                                                 }
    1966             :                                         }
    1967             :                                 } else {
    1968           0 :                                         ZCG(cache_opline) = NULL;
    1969           0 :                                         ZCG(cache_persistent_script) = NULL;
    1970           0 :                                         return accelerator_orig_zend_resolve_path(filename, filename_len);
    1971             :                                 }
    1972             :                         }
    1973             : 
    1974             :                         /* find the full real path */
    1975         850 :                         resolved_path = accelerator_orig_zend_resolve_path(filename, filename_len);
    1976             : 
    1977         850 :                         if (resolved_path) {
    1978             :                                 /* lookup by real path */
    1979         850 :                                 zend_accel_hash_entry *bucket = zend_accel_hash_find_entry(&ZCSG(hash), resolved_path);
    1980         850 :                                 if (bucket) {
    1981           0 :                                         zend_persistent_script *persistent_script = (zend_persistent_script *)bucket->data;
    1982           0 :                                         if (!persistent_script->corrupted) {
    1983           0 :                                                 if (key) {
    1984             :                                                         /* add another "key" for the same bucket */
    1985           0 :                                                         HANDLE_BLOCK_INTERRUPTIONS();
    1986           0 :                                                         SHM_UNPROTECT();
    1987           0 :                                                         zend_shared_alloc_lock();
    1988           0 :                                                         zend_accel_add_key(key, key_length, bucket);
    1989           0 :                                                         zend_shared_alloc_unlock();
    1990           0 :                                                         SHM_PROTECT();
    1991           0 :                                                         HANDLE_UNBLOCK_INTERRUPTIONS();
    1992             :                                                 } else {
    1993           0 :                                                         ZCG(key_len) = 0;
    1994             :                                                 }
    1995           0 :                                                 ZCG(cache_opline) = EG(current_execute_data) ? EG(current_execute_data)->opline : NULL;
    1996           0 :                                                 ZCG(cache_persistent_script) = persistent_script;
    1997           0 :                                                 return resolved_path;
    1998             :                                         }
    1999             :                                 }
    2000             :                         }
    2001             : 
    2002         850 :                         ZCG(cache_opline) = NULL;
    2003         850 :                         ZCG(cache_persistent_script) = NULL;
    2004         850 :                         return resolved_path;
    2005             :                 }
    2006             :         }
    2007         119 :         ZCG(cache_opline) = NULL;
    2008         119 :         ZCG(cache_persistent_script) = NULL;
    2009         119 :         return accelerator_orig_zend_resolve_path(filename, filename_len);
    2010             : }
    2011             : 
    2012         477 : static void zend_reset_cache_vars(void)
    2013             : {
    2014         477 :         ZSMMG(memory_exhausted) = 0;
    2015         477 :         ZCSG(hits) = 0;
    2016         477 :         ZCSG(misses) = 0;
    2017         477 :         ZCSG(blacklist_misses) = 0;
    2018         477 :         ZSMMG(wasted_shared_memory) = 0;
    2019         477 :         ZCSG(restart_pending) = 0;
    2020         477 :         ZCSG(force_restart_time) = 0;
    2021         477 : }
    2022             : 
    2023         478 : static void accel_reset_pcre_cache(void)
    2024             : {
    2025             :         Bucket *p;
    2026             : 
    2027         480 :         ZEND_HASH_FOREACH_BUCKET(&PCRE_G(pcre_cache), p) {
    2028             :                 /* Remove PCRE cache entries with inconsistent keys */
    2029           1 :                 if (zend_accel_in_shm(p->key)) {
    2030           1 :                         p->key = NULL;
    2031           1 :                         zend_hash_del_bucket(&PCRE_G(pcre_cache), p);
    2032             :                 }
    2033             :         } ZEND_HASH_FOREACH_END();
    2034         478 : }
    2035             : 
    2036         478 : static void accel_activate(void)
    2037             : {
    2038         478 :         zend_bool reset_pcre = 0;
    2039             : 
    2040         478 :         if (!ZCG(enabled) || !accel_startup_ok) {
    2041           0 :                 return;
    2042             :         }
    2043             : 
    2044         478 :         if (!ZCG(function_table).nTableSize) {
    2045         478 :                 zend_hash_init(&ZCG(function_table), zend_hash_num_elements(CG(function_table)), NULL, ZEND_FUNCTION_DTOR, 1);
    2046         478 :                 zend_accel_copy_internal_functions();
    2047             :         }
    2048             : 
    2049             :         /* PHP-5.4 and above return "double", but we use 1 sec precision */
    2050         478 :         ZCG(auto_globals_mask) = 0;
    2051         478 :         ZCG(request_time) = (time_t)sapi_get_request_time();
    2052         478 :         ZCG(cache_opline) = NULL;
    2053         478 :         ZCG(cache_persistent_script) = NULL;
    2054         478 :         ZCG(include_path_key_len) = 0;
    2055         478 :         ZCG(include_path_check) = 1;
    2056             : 
    2057             :         /* check if ZCG(function_table) wasn't somehow polluted on the way */
    2058         478 :         if (ZCG(internal_functions_count) != (zend_long)zend_hash_num_elements(&ZCG(function_table))) {
    2059           0 :                 zend_accel_error(ACCEL_LOG_WARNING, "Internal functions count changed - was %d, now %d", ZCG(internal_functions_count), zend_hash_num_elements(&ZCG(function_table)));
    2060             :         }
    2061             : 
    2062         478 :         ZCG(cwd) = NULL;
    2063         478 :         ZCG(cwd_key_len) = 0;
    2064         478 :         ZCG(cwd_check) = 1;
    2065             : 
    2066             : #ifdef HAVE_OPCACHE_FILE_CACHE
    2067         478 :         if (ZCG(accel_directives).file_cache_only) {
    2068           1 :                 return;
    2069             :         }
    2070             : #endif
    2071             : 
    2072         477 :         HANDLE_BLOCK_INTERRUPTIONS();
    2073         477 :         SHM_UNPROTECT();
    2074             : 
    2075         477 :         if (ZCG(counted)) {
    2076             : #ifdef ZTS
    2077             :                 zend_accel_error(ACCEL_LOG_WARNING, "Stuck count for thread id %d", tsrm_thread_id());
    2078             : #else
    2079           0 :                 zend_accel_error(ACCEL_LOG_WARNING, "Stuck count for pid %d", getpid());
    2080             : #endif
    2081           0 :                 accel_unlock_all();
    2082           0 :                 ZCG(counted) = 0;
    2083             :         }
    2084             : 
    2085         477 :         if (ZCSG(restart_pending)) {
    2086           0 :                 zend_shared_alloc_lock();
    2087           0 :                 if (ZCSG(restart_pending) != 0) { /* check again, to ensure that the cache wasn't already cleaned by another process */
    2088           0 :                         if (accel_is_inactive() == SUCCESS) {
    2089           0 :                                 zend_accel_error(ACCEL_LOG_DEBUG, "Restarting!");
    2090           0 :                                 ZCSG(restart_pending) = 0;
    2091           0 :                                 switch ZCSG(restart_reason) {
    2092             :                                         case ACCEL_RESTART_OOM:
    2093           0 :                                                 ZCSG(oom_restarts)++;
    2094           0 :                                                 break;
    2095             :                                         case ACCEL_RESTART_HASH:
    2096           0 :                                                 ZCSG(hash_restarts)++;
    2097           0 :                                                 break;
    2098             :                                         case ACCEL_RESTART_USER:
    2099           0 :                                                 ZCSG(manual_restarts)++;
    2100             :                                                 break;
    2101             :                                 }
    2102           0 :                                 accel_restart_enter();
    2103             : 
    2104           0 :                                 zend_reset_cache_vars();
    2105           0 :                                 zend_accel_hash_clean(&ZCSG(hash));
    2106             : 
    2107             : #if !defined(ZTS)
    2108           0 :                                 if (ZCG(accel_directives).interned_strings_buffer) {
    2109           0 :                                         accel_interned_strings_restore_state();
    2110             :                                 }
    2111             : #endif
    2112             : 
    2113           0 :                                 zend_shared_alloc_restore_state();
    2114           0 :                                 ZCSG(accelerator_enabled) = ZCSG(cache_status_before_restart);
    2115           0 :                                 if (ZCSG(last_restart_time) < ZCG(request_time)) {
    2116           0 :                                         ZCSG(last_restart_time) = ZCG(request_time);
    2117             :                                 } else {
    2118           0 :                                         ZCSG(last_restart_time)++;
    2119             :                                 }
    2120           0 :                                 accel_restart_leave();
    2121             :                         }
    2122             :                 } else {
    2123           0 :                         reset_pcre = 1;
    2124             :                 }
    2125           0 :                 zend_shared_alloc_unlock();
    2126             :         }
    2127             : 
    2128         477 :         SHM_PROTECT();
    2129         477 :         HANDLE_UNBLOCK_INTERRUPTIONS();
    2130             : 
    2131         477 :         if (ZCSG(last_restart_time) != ZCG(last_restart_time)) {
    2132             :                 /* SHM was reinitialized. */
    2133           0 :                 ZCG(last_restart_time) = ZCSG(last_restart_time);
    2134             : 
    2135             :                 /* Reset in-process realpath cache */
    2136           0 :                 realpath_cache_clean();
    2137             : 
    2138           0 :                 accel_reset_pcre_cache();
    2139         477 :         } else if (reset_pcre) {
    2140           0 :                 accel_reset_pcre_cache();
    2141             :         }
    2142             : }
    2143             : 
    2144             : #if !ZEND_DEBUG
    2145             : 
    2146             : /* Fast Request Shutdown
    2147             :  * =====================
    2148             :  * Zend Memory Manager frees memory by its own. We don't have to free each
    2149             :  * allocated block separately, but we like to call all the destructors and
    2150             :  * callbacks in exactly the same order.
    2151             :  */
    2152             : static void accel_fast_hash_destroy(HashTable *ht);
    2153             : 
    2154           0 : static void accel_fast_zval_dtor(zval *zvalue)
    2155             : {
    2156             : tail_call:
    2157           0 :         switch (Z_TYPE_P(zvalue)) {
    2158             :                 case IS_ARRAY:
    2159           0 :                         GC_REMOVE_FROM_BUFFER(Z_ARR_P(zvalue));
    2160           0 :                         if (Z_ARR_P(zvalue) != &EG(symbol_table)) {
    2161             :                                 /* break possible cycles */
    2162           0 :                                 ZVAL_NULL(zvalue);
    2163           0 :                                 accel_fast_hash_destroy(Z_ARRVAL_P(zvalue));
    2164             :                         }
    2165           0 :                         break;
    2166             :                 case IS_OBJECT:
    2167           0 :                         OBJ_RELEASE(Z_OBJ_P(zvalue));
    2168           0 :                         break;
    2169             :                 case IS_RESOURCE:
    2170           0 :                         zend_list_delete(Z_RES_P(zvalue));
    2171           0 :                         break;
    2172             :                 case IS_REFERENCE: {
    2173           0 :                                 zend_reference *ref = Z_REF_P(zvalue);
    2174             : 
    2175           0 :                                 if (--GC_REFCOUNT(ref) == 0) {
    2176           0 :                                         if (Z_REFCOUNTED(ref->val) && Z_DELREF(ref->val) == 0) {
    2177           0 :                                                 zvalue = &ref->val;
    2178           0 :                                                 goto tail_call;
    2179             :                                         }
    2180             :                                 }
    2181             :                         }
    2182             :                         break;
    2183             :         }
    2184           0 : }
    2185             : 
    2186           0 : static void accel_fast_hash_destroy(HashTable *ht)
    2187             : {
    2188           0 :         Bucket *p = ht->arData;
    2189           0 :         Bucket *end = p + ht->nNumUsed;
    2190             : 
    2191           0 :         while (p != end) {
    2192           0 :                 if (Z_REFCOUNTED(p->val) && Z_DELREF(p->val) == 0) {
    2193           0 :                         accel_fast_zval_dtor(&p->val);
    2194             :                 }
    2195           0 :                 p++;
    2196             :         }
    2197           0 : }
    2198             : 
    2199           0 : static inline void zend_accel_fast_del_bucket(HashTable *ht, uint32_t idx, Bucket *p)
    2200             : {
    2201           0 :         uint32_t nIndex = p->h | ht->nTableMask;
    2202           0 :         uint32_t i = HT_HASH(ht, nIndex);
    2203             : 
    2204           0 :         ht->nNumOfElements--;
    2205           0 :         if (idx != i) {
    2206           0 :                 Bucket *prev = HT_HASH_TO_BUCKET(ht, i);
    2207           0 :                 while (Z_NEXT(prev->val) != idx) {
    2208           0 :                         i = Z_NEXT(prev->val);
    2209           0 :                         prev = HT_HASH_TO_BUCKET(ht, i);
    2210             :                 }
    2211           0 :                 Z_NEXT(prev->val) = Z_NEXT(p->val);
    2212             :         } else {
    2213           0 :                 HT_HASH(ht, p->h | ht->nTableMask) = Z_NEXT(p->val);
    2214             :         }
    2215           0 : }
    2216             : 
    2217           0 : static void zend_accel_fast_shutdown(void)
    2218             : {
    2219           0 :         if (EG(full_tables_cleanup)) {
    2220           0 :                 return;
    2221             :         }
    2222             : 
    2223           0 :         if (EG(objects_store).top > 1 || zend_hash_num_elements(&EG(regular_list)) > 0) {
    2224             :                 /* We don't have to destroy all zvals if they cannot call any destructors */
    2225           0 :                 zend_try {
    2226           0 :                         ZEND_HASH_REVERSE_FOREACH(&EG(symbol_table), 0) {
    2227           0 :                                 if (Z_REFCOUNTED(_p->val) && Z_DELREF(_p->val) == 0) {
    2228           0 :                                         accel_fast_zval_dtor(&_p->val);
    2229             :                                 }
    2230           0 :                                 zend_accel_fast_del_bucket(&EG(symbol_table), HT_IDX_TO_HASH(_idx-1), _p);
    2231             :                         } ZEND_HASH_FOREACH_END();
    2232           0 :                 } zend_end_try();
    2233           0 :                 zend_hash_init(&EG(symbol_table), 8, NULL, NULL, 0);
    2234             : 
    2235           0 :                 ZEND_HASH_REVERSE_FOREACH(EG(function_table), 0) {
    2236           0 :                         zend_function *func = Z_PTR(_p->val);
    2237             : 
    2238           0 :                         if (func->type == ZEND_INTERNAL_FUNCTION) {
    2239           0 :                                 break;
    2240             :                         } else {
    2241           0 :                                 if (func->op_array.static_variables) {
    2242           0 :                                         if (!(GC_FLAGS(func->op_array.static_variables) & IS_ARRAY_IMMUTABLE)) {
    2243           0 :                                                 if (--GC_REFCOUNT(func->op_array.static_variables) == 0) {
    2244           0 :                                                         accel_fast_hash_destroy(func->op_array.static_variables);
    2245             :                                                 }
    2246             :                                         }
    2247             :                                 }
    2248           0 :                                 zend_accel_fast_del_bucket(EG(function_table), HT_IDX_TO_HASH(_idx-1), _p);
    2249             :                         }
    2250             :                 } ZEND_HASH_FOREACH_END();
    2251             : 
    2252           0 :                 ZEND_HASH_REVERSE_FOREACH(EG(class_table), 0) {
    2253           0 :                         zend_class_entry *ce = Z_PTR(_p->val);
    2254             : 
    2255           0 :                         if (ce->type == ZEND_INTERNAL_CLASS) {
    2256           0 :                                 break;
    2257             :                         } else {
    2258           0 :                                 if (ce->ce_flags & ZEND_HAS_STATIC_IN_METHODS) {
    2259             :                                         zend_function *func;
    2260             : 
    2261           0 :                                         ZEND_HASH_FOREACH_PTR(&ce->function_table, func) {
    2262           0 :                                                 if (func->type == ZEND_USER_FUNCTION) {
    2263           0 :                                                         if (func->op_array.static_variables) {
    2264           0 :                                                                 if (!(GC_FLAGS(func->op_array.static_variables) & IS_ARRAY_IMMUTABLE)) {
    2265           0 :                                                                         if (--GC_REFCOUNT(func->op_array.static_variables) == 0) {
    2266           0 :                                                                                 accel_fast_hash_destroy(func->op_array.static_variables);
    2267             :                                                                         }
    2268             :                                                                 }
    2269           0 :                                                                 func->op_array.static_variables = NULL;
    2270             :                                                         }
    2271             :                                                 }
    2272             :                                         } ZEND_HASH_FOREACH_END();
    2273             :                                 }
    2274           0 :                                 if (ce->static_members_table) {
    2275             :                                         int i;
    2276             : 
    2277           0 :                                         for (i = 0; i < ce->default_static_members_count; i++) {
    2278           0 :                                                 zval *zv = &ce->static_members_table[i];
    2279           0 :                                                 ZVAL_UNDEF(&ce->static_members_table[i]);
    2280           0 :                                                 if (Z_REFCOUNTED_P(zv) && Z_DELREF_P(zv) == 0) {
    2281           0 :                                                         accel_fast_zval_dtor(zv);
    2282             :                                                 }
    2283             :                                         }
    2284           0 :                                         ce->static_members_table = NULL;
    2285             :                                 }
    2286           0 :                                 zend_accel_fast_del_bucket(EG(class_table), HT_IDX_TO_HASH(_idx-1), _p);
    2287             :                         }
    2288             :                 } ZEND_HASH_FOREACH_END();
    2289             : 
    2290             :         } else {
    2291             : 
    2292           0 :                 zend_hash_init(&EG(symbol_table), 8, NULL, NULL, 0);
    2293             : 
    2294           0 :                 ZEND_HASH_REVERSE_FOREACH(EG(function_table), 0) {
    2295           0 :                         zend_function *func = Z_PTR(_p->val);
    2296             : 
    2297           0 :                         if (func->type == ZEND_INTERNAL_FUNCTION) {
    2298           0 :                                 break;
    2299             :                         } else {
    2300           0 :                                 zend_accel_fast_del_bucket(EG(function_table), HT_IDX_TO_HASH(_idx-1), _p);
    2301             :                         }
    2302             :                 } ZEND_HASH_FOREACH_END();
    2303             : 
    2304           0 :                 ZEND_HASH_REVERSE_FOREACH(EG(class_table), 0) {
    2305           0 :                         zend_class_entry *ce = Z_PTR(_p->val);
    2306             : 
    2307           0 :                         if (ce->type == ZEND_INTERNAL_CLASS) {
    2308           0 :                                 break;
    2309             :                         } else {
    2310           0 :                                 zend_accel_fast_del_bucket(EG(class_table), HT_IDX_TO_HASH(_idx-1), _p);
    2311             :                         }
    2312             :                 } ZEND_HASH_FOREACH_END();
    2313             :         }
    2314             : 
    2315           0 :         ZEND_HASH_REVERSE_FOREACH(EG(zend_constants), 0) {
    2316           0 :                 zend_constant *c = Z_PTR(_p->val);
    2317             : 
    2318           0 :                 if (c->flags & CONST_PERSISTENT) {
    2319           0 :                         break;
    2320             :                 } else {
    2321           0 :                         zend_accel_fast_del_bucket(EG(zend_constants), HT_IDX_TO_HASH(_idx-1), _p);
    2322             :                 }
    2323             :         } ZEND_HASH_FOREACH_END();
    2324           0 :         EG(function_table)->nNumUsed = EG(function_table)->nNumOfElements;
    2325           0 :         EG(class_table)->nNumUsed = EG(class_table)->nNumOfElements;
    2326           0 :         EG(zend_constants)->nNumUsed = EG(zend_constants)->nNumOfElements;
    2327             : 
    2328           0 :         CG(unclean_shutdown) = 1;
    2329             : }
    2330             : #endif
    2331             : 
    2332       23795 : int accel_post_deactivate(void)
    2333             : {
    2334       23795 :         if (!ZCG(enabled) || !accel_startup_ok) {
    2335       23317 :                 return SUCCESS;
    2336             :         }
    2337             : 
    2338         478 :         zend_shared_alloc_safe_unlock(); /* be sure we didn't leave cache locked */
    2339         478 :         accel_unlock_all();
    2340         478 :         ZCG(counted) = 0;
    2341             : 
    2342         478 :         return SUCCESS;
    2343             : }
    2344             : 
    2345         478 : static void accel_deactivate(void)
    2346             : {
    2347             :         /* ensure that we restore function_table and class_table
    2348             :          * In general, they're restored by persistent_compile_file(), but in case
    2349             :          * the script is aborted abnormally, they may become messed up.
    2350             :          */
    2351             : 
    2352         478 :         if (ZCG(cwd)) {
    2353          77 :                 zend_string_release(ZCG(cwd));
    2354          77 :                 ZCG(cwd) = NULL;
    2355             :         }
    2356             : 
    2357         478 :         if (!ZCG(enabled) || !accel_startup_ok) {
    2358           0 :                 return;
    2359             :         }
    2360             : 
    2361             : #if !ZEND_DEBUG
    2362         478 :         if (ZCG(accel_directives).fast_shutdown && is_zend_mm()) {
    2363           0 :                 zend_accel_fast_shutdown();
    2364             :         }
    2365             : #endif
    2366             : }
    2367             : 
    2368       23341 : static int accelerator_remove_cb(zend_extension *element1, zend_extension *element2)
    2369             : {
    2370             :         (void)element2; /* keep the compiler happy */
    2371             : 
    2372       23341 :         if (!strcmp(element1->name, ACCELERATOR_PRODUCT_NAME )) {
    2373       23341 :                 element1->startup = NULL;
    2374             : #if 0
    2375             :                 /* We have to call shutdown callback it to free TS resources */
    2376             :                 element1->shutdown = NULL;
    2377             : #endif
    2378       23341 :                 element1->activate = NULL;
    2379       23341 :                 element1->deactivate = NULL;
    2380       23341 :                 element1->op_array_handler = NULL;
    2381             : 
    2382             : #ifdef __DEBUG_MESSAGES__
    2383             :         fprintf(stderr, ACCELERATOR_PRODUCT_NAME " is disabled: %s\n", (zps_failure_reason ? zps_failure_reason : "unknown error"));
    2384             :         fflush(stderr);
    2385             : #endif
    2386             :         }
    2387             : 
    2388       23341 :         return 0;
    2389             : }
    2390             : 
    2391       23341 : static void zps_startup_failure(char *reason, char *api_reason, int (*cb)(zend_extension *, zend_extension *))
    2392             : {
    2393       23341 :         accel_startup_ok = 0;
    2394       23341 :         zps_failure_reason = reason;
    2395       23341 :         zps_api_failure_reason = api_reason?api_reason:reason;
    2396       23341 :         zend_llist_del_element(&zend_extensions, NULL, (int (*)(void *, void *))cb);
    2397       23341 : }
    2398             : 
    2399       23819 : static inline int accel_find_sapi(void)
    2400             : {
    2401             :         static const char *supported_sapis[] = {
    2402             :                 "apache",
    2403             :                 "fastcgi",
    2404             :                 "cli-server",
    2405             :                 "cgi-fcgi",
    2406             :                 "fpm-fcgi",
    2407             :                 "isapi",
    2408             :                 "apache2filter",
    2409             :                 "apache2handler",
    2410             :                 "litespeed",
    2411             :                 "uwsgi",
    2412             :                 NULL
    2413             :         };
    2414             :         const char **sapi_name;
    2415             : 
    2416       23819 :         if (sapi_module.name) {
    2417      259391 :                 for (sapi_name = supported_sapis; *sapi_name; sapi_name++) {
    2418      235946 :                         if (strcmp(sapi_module.name, *sapi_name) == 0) {
    2419         374 :                                 return SUCCESS;
    2420             :                         }
    2421             :                 }
    2422       23549 :                 if (ZCG(accel_directives).enable_cli && (
    2423         104 :                     strcmp(sapi_module.name, "cli") == 0
    2424         104 :                   || strcmp(sapi_module.name, "phpdbg") == 0)) {
    2425         104 :                         return SUCCESS;
    2426             :                 }
    2427             :         }
    2428             : 
    2429       23341 :         return FAILURE;
    2430             : }
    2431             : 
    2432         477 : static int zend_accel_init_shm(void)
    2433             : {
    2434         477 :         zend_shared_alloc_lock();
    2435             : 
    2436         477 :         accel_shared_globals = zend_shared_alloc(sizeof(zend_accel_shared_globals));
    2437         477 :         if (!accel_shared_globals) {
    2438           0 :                 zend_accel_error(ACCEL_LOG_FATAL, "Insufficient shared memory!");
    2439           0 :                 zend_shared_alloc_unlock();
    2440           0 :                 return FAILURE;
    2441             :         }
    2442         477 :         ZSMMG(app_shared_globals) = accel_shared_globals;
    2443             : 
    2444         477 :         zend_accel_hash_init(&ZCSG(hash), ZCG(accel_directives).max_accelerated_files);
    2445             : 
    2446         477 :         ZCSG(interned_strings_start) = ZCSG(interned_strings_end) = NULL;
    2447             : # ifndef ZTS
    2448         477 :         zend_hash_init(&ZCSG(interned_strings), (ZCG(accel_directives).interned_strings_buffer * 1024 * 1024) / _ZSTR_STRUCT_SIZE(8 /* average string length */), NULL, NULL, 1);
    2449         477 :         if (ZCG(accel_directives).interned_strings_buffer) {
    2450             :                 void *data;
    2451             : 
    2452         475 :                 ZCSG(interned_strings).nTableMask = -ZCSG(interned_strings).nTableSize;
    2453         475 :                 data = zend_shared_alloc(HT_SIZE(&ZCSG(interned_strings)));
    2454         475 :                 ZCSG(interned_strings_start) = zend_shared_alloc((ZCG(accel_directives).interned_strings_buffer * 1024 * 1024));
    2455         475 :                 if (!data || !ZCSG(interned_strings_start)) {
    2456           0 :                         zend_accel_error(ACCEL_LOG_FATAL, ACCELERATOR_PRODUCT_NAME " cannot allocate buffer for interned strings");
    2457           0 :                         zend_shared_alloc_unlock();
    2458           0 :                         return FAILURE;
    2459             :                 }
    2460         475 :                 HT_SET_DATA_ADDR(&ZCSG(interned_strings), data);
    2461         475 :                 HT_HASH_RESET(&ZCSG(interned_strings));
    2462         475 :                 ZCSG(interned_strings_end)   = ZCSG(interned_strings_start) + (ZCG(accel_directives).interned_strings_buffer * 1024 * 1024);
    2463         475 :                 ZCSG(interned_strings_top)   = ZCSG(interned_strings_start);
    2464             : 
    2465             : //              orig_interned_strings_start = CG(interned_strings_start);
    2466             : //              orig_interned_strings_end = CG(interned_strings_end);
    2467             : //              CG(interned_strings_start) = ZCSG(interned_strings_start);
    2468             : //              CG(interned_strings_end) = ZCSG(interned_strings_end);
    2469             :         }
    2470             : # endif
    2471             : 
    2472         477 :         orig_new_interned_string = zend_new_interned_string;
    2473         477 :         orig_interned_strings_snapshot = zend_interned_strings_snapshot;
    2474         477 :         orig_interned_strings_restore = zend_interned_strings_restore;
    2475         477 :         zend_new_interned_string = accel_new_interned_string_for_php;
    2476         477 :         zend_interned_strings_snapshot = accel_interned_strings_snapshot_for_php;
    2477         477 :         zend_interned_strings_restore = accel_interned_strings_restore_for_php;
    2478             : 
    2479             : # ifndef ZTS
    2480         477 :         if (ZCG(accel_directives).interned_strings_buffer) {
    2481         475 :                 accel_use_shm_interned_strings();
    2482         475 :                 accel_interned_strings_save_state();
    2483             :         }
    2484             : # endif
    2485             : 
    2486         477 :         zend_reset_cache_vars();
    2487             : 
    2488         477 :         ZCSG(oom_restarts) = 0;
    2489         477 :         ZCSG(hash_restarts) = 0;
    2490         477 :         ZCSG(manual_restarts) = 0;
    2491             : 
    2492         477 :         ZCSG(accelerator_enabled) = 1;
    2493         477 :         ZCSG(start_time) = zend_accel_get_time();
    2494         477 :         ZCSG(last_restart_time) = 0;
    2495         477 :         ZCSG(restart_in_progress) = 0;
    2496             : 
    2497         477 :         zend_shared_alloc_unlock();
    2498             : 
    2499         477 :         return SUCCESS;
    2500             : }
    2501             : 
    2502       23819 : static void accel_globals_ctor(zend_accel_globals *accel_globals)
    2503             : {
    2504             : #if defined(COMPILE_DL_OPCACHE) && defined(ZTS)
    2505             :         ZEND_TSRMLS_CACHE_UPDATE();
    2506             : #endif
    2507       23819 :         memset(accel_globals, 0, sizeof(zend_accel_globals));
    2508       23819 : }
    2509             : 
    2510     1105663 : static void accel_globals_internal_func_dtor(zval *zv)
    2511             : {
    2512     1105663 :         free(Z_PTR_P(zv));
    2513     1105663 : }
    2514             : 
    2515       23795 : static void accel_globals_dtor(zend_accel_globals *accel_globals)
    2516             : {
    2517       23795 :         if (accel_globals->function_table.nTableSize) {
    2518         478 :                 accel_globals->function_table.pDestructor = accel_globals_internal_func_dtor;
    2519         478 :                 zend_hash_destroy(&accel_globals->function_table);
    2520             :         }
    2521       23795 : }
    2522             : 
    2523             : #define ZEND_BIN_ID "BIN_" ZEND_TOSTR(SIZEOF_CHAR) ZEND_TOSTR(SIZEOF_INT) ZEND_TOSTR(SIZEOF_LONG) ZEND_TOSTR(SIZEOF_SIZE_T) ZEND_TOSTR(SIZEOF_ZEND_LONG) ZEND_TOSTR(ZEND_MM_ALIGNMENT)
    2524             : 
    2525       23819 : static void accel_gen_system_id(void)
    2526             : {
    2527             :         PHP_MD5_CTX context;
    2528             :         unsigned char digest[16], c;
    2529       23819 :         char *md5str = ZCG(system_id);
    2530             :         int i;
    2531             : 
    2532       23819 :         PHP_MD5Init(&context);
    2533       23819 :         PHP_MD5Update(&context, PHP_VERSION, sizeof(PHP_VERSION)-1);
    2534       23819 :         PHP_MD5Update(&context, ZEND_EXTENSION_BUILD_ID, sizeof(ZEND_EXTENSION_BUILD_ID)-1);
    2535       23819 :         PHP_MD5Update(&context, ZEND_BIN_ID, sizeof(ZEND_BIN_ID)-1);
    2536             :         if (strstr(PHP_VERSION, "-dev") != 0) {
    2537             :                 /* Development versions may be changed from build to build */
    2538       23819 :                 PHP_MD5Update(&context, __DATE__, sizeof(__DATE__)-1);
    2539       23819 :                 PHP_MD5Update(&context, __TIME__, sizeof(__TIME__)-1);
    2540             :         }
    2541       23819 :         PHP_MD5Final(digest, &context);
    2542      404923 :         for (i = 0; i < 16; i++) {
    2543      381104 :                 c = digest[i] >> 4;
    2544      381104 :                 c = (c <= 9) ? c + '0' : c - 10 + 'a';
    2545      381104 :                 md5str[i * 2] = c;
    2546      381104 :                 c = digest[i] &  0x0f;
    2547      381104 :                 c = (c <= 9) ? c + '0' : c - 10 + 'a';
    2548      381104 :                 md5str[(i * 2) + 1] = c;
    2549             :         }
    2550       23819 : }
    2551             : 
    2552             : #ifdef HAVE_HUGE_CODE_PAGES
    2553             : # ifndef _WIN32
    2554             : #  include <sys/mman.h>
    2555             : #  ifndef MAP_ANON
    2556             : #   ifdef MAP_ANONYMOUS
    2557             : #    define MAP_ANON MAP_ANONYMOUS
    2558             : #   endif
    2559             : #  endif
    2560             : #  ifndef MAP_FAILED
    2561             : #   define MAP_FAILED ((void*)-1)
    2562             : #  endif
    2563             : # endif
    2564             : 
    2565             : # if defined(MAP_HUGETLB) || defined(MADV_HUGEPAGE)
    2566           0 : static int accel_remap_huge_pages(void *start, size_t size, const char *name, size_t offset)
    2567             : {
    2568           0 :         void *ret = MAP_FAILED;
    2569             :         void *mem;
    2570             : 
    2571           0 :         mem = mmap(NULL, size,
    2572             :                 PROT_READ | PROT_WRITE,
    2573             :                 MAP_PRIVATE | MAP_ANONYMOUS,
    2574             :                 -1, 0);
    2575           0 :         if (mem == MAP_FAILED) {
    2576           0 :                 zend_error(E_WARNING,
    2577             :                         ACCELERATOR_PRODUCT_NAME " huge_code_pages: mmap failed: %s (%d)",
    2578             :                         strerror(errno), errno);
    2579           0 :                 return -1;
    2580             :         }
    2581           0 :         memcpy(mem, start, size);
    2582             : 
    2583             : #  ifdef MAP_HUGETLB
    2584           0 :         ret = mmap(start, size,
    2585             :                 PROT_READ | PROT_WRITE | PROT_EXEC,
    2586             :                 MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED | MAP_HUGETLB,
    2587             :                 -1, 0);
    2588             : #  endif
    2589           0 :         if (ret == MAP_FAILED) {
    2590           0 :                 ret = mmap(start, size,
    2591             :                         PROT_READ | PROT_WRITE | PROT_EXEC,
    2592             :                         MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED,
    2593             :                         -1, 0);
    2594             :                 /* this should never happen? */
    2595             :                 ZEND_ASSERT(ret != MAP_FAILED);
    2596             : #  ifdef MADV_HUGEPAGE
    2597             :                 if (-1 == madvise(start, size, MADV_HUGEPAGE)) {
    2598             :                         memcpy(start, mem, size);
    2599             :                         mprotect(start, size, PROT_READ | PROT_EXEC);
    2600             :                         munmap(mem, size);
    2601             :                         zend_error(E_WARNING,
    2602             :                                 ACCELERATOR_PRODUCT_NAME " huge_code_pages: madvise(HUGEPAGE) failed: %s (%d)",
    2603             :                                 strerror(errno), errno);
    2604             :                         return -1;
    2605             :                 }
    2606             : #  else
    2607           0 :                 memcpy(start, mem, size);
    2608           0 :                 mprotect(start, size, PROT_READ | PROT_EXEC);
    2609           0 :                 munmap(mem, size);
    2610           0 :                 zend_error(E_WARNING,
    2611             :                         ACCELERATOR_PRODUCT_NAME " huge_code_pages: mmap(HUGETLB) failed: %s (%d)",
    2612             :                         strerror(errno), errno);
    2613           0 :                 return -1;
    2614             : #  endif
    2615             :         }
    2616             : 
    2617           0 :         if (ret == start) {
    2618           0 :                 memcpy(start, mem, size);
    2619           0 :                 mprotect(start, size, PROT_READ | PROT_EXEC);
    2620             :         }
    2621           0 :         munmap(mem, size);
    2622             : 
    2623           0 :         return (ret == start) ? 0 : -1;
    2624             : }
    2625             : 
    2626           0 : static void accel_move_code_to_huge_pages(void)
    2627             : {
    2628             :         FILE *f;
    2629           0 :         long unsigned int huge_page_size = 2 * 1024 * 1024;
    2630             : 
    2631           0 :         f = fopen("/proc/self/maps", "r");
    2632           0 :         if (f) {
    2633             :                 long unsigned int  start, end, offset, inode;
    2634             :                 char perm[5], dev[6], name[MAXPATHLEN];
    2635             :                 int ret;
    2636             : 
    2637           0 :                 ret = fscanf(f, "%lx-%lx %4s %lx %5s %ld %s\n", &start, &end, perm, &offset, dev, &inode, name);
    2638           0 :                 if (ret == 7 && perm[0] == 'r' && perm[1] == '-' && perm[2] == 'x' && name[0] == '/') {
    2639           0 :                         long unsigned int  seg_start = ZEND_MM_ALIGNED_SIZE_EX(start, huge_page_size);
    2640           0 :                         long unsigned int  seg_end = (end & ~(huge_page_size-1L));
    2641             : 
    2642           0 :                         if (seg_end > seg_start) {
    2643           0 :                                 zend_accel_error(ACCEL_LOG_DEBUG, "remap to huge page %lx-%lx %s \n", seg_start, seg_end, name);
    2644           0 :                                 accel_remap_huge_pages((void*)seg_start, seg_end - seg_start, name, offset + seg_start - start);
    2645             :                         }
    2646             :                 }
    2647           0 :                 fclose(f);
    2648             :         }
    2649           0 : }
    2650             : # else
    2651             : static void accel_move_code_to_huge_pages(void)
    2652             : {
    2653             :         zend_error(E_WARNING, ACCELERATOR_PRODUCT_NAME ": opcache.huge_code_pages has no affect as huge page is not supported");
    2654             :         return;
    2655             : }
    2656             : # endif /* defined(MAP_HUGETLB) || defined(MADV_HUGEPAGE) */
    2657             : #endif /* HAVE_HUGE_CODE_PAGES */
    2658             : 
    2659       23819 : static int accel_startup(zend_extension *extension)
    2660             : {
    2661             :         zend_function *func;
    2662             :         zend_ini_entry *ini_entry;
    2663             : 
    2664             : #ifdef ZTS
    2665             :         accel_globals_id = ts_allocate_id(&accel_globals_id, sizeof(zend_accel_globals), (ts_allocate_ctor) accel_globals_ctor, (ts_allocate_dtor) accel_globals_dtor);
    2666             : #else
    2667       23819 :         accel_globals_ctor(&accel_globals);
    2668             : #endif
    2669             : 
    2670             : #ifdef ZEND_WIN32
    2671             :         _setmaxstdio(2048); /* The default configuration is limited to 512 stdio files */
    2672             : #endif
    2673             : 
    2674       23819 :         if (start_accel_module() == FAILURE) {
    2675           0 :                 accel_startup_ok = 0;
    2676           0 :                 zend_error(E_WARNING, ACCELERATOR_PRODUCT_NAME ": module registration failed!");
    2677           0 :                 return FAILURE;
    2678             :         }
    2679             : 
    2680       23819 :         accel_gen_system_id();
    2681             : 
    2682             : #ifdef HAVE_HUGE_CODE_PAGES
    2683       23819 :         if (ZCG(accel_directives).huge_code_pages &&
    2684           0 :             (strcmp(sapi_module.name, "cli") == 0 ||
    2685           0 :              strcmp(sapi_module.name, "cli-server") == 0 ||
    2686           0 :                  strcmp(sapi_module.name, "cgi-fcgi") == 0 ||
    2687           0 :                  strcmp(sapi_module.name, "fpm-fcgi") == 0)) {
    2688           0 :                 accel_move_code_to_huge_pages();
    2689             :         }
    2690             : #endif
    2691             : 
    2692             :         /* no supported SAPI found - disable acceleration and stop initialization */
    2693       23819 :         if (accel_find_sapi() == FAILURE) {
    2694       23341 :                 accel_startup_ok = 0;
    2695       69960 :                 if (!ZCG(accel_directives).enable_cli &&
    2696       23341 :                     strcmp(sapi_module.name, "cli") == 0) {
    2697       23278 :                         zps_startup_failure("Opcode Caching is disabled for CLI", NULL, accelerator_remove_cb);
    2698             :                 } else {
    2699          63 :                         zps_startup_failure("Opcode Caching is only supported in Apache, ISAPI, FPM, FastCGI and LiteSpeed SAPIs", NULL, accelerator_remove_cb);
    2700             :                 }
    2701       23341 :                 return SUCCESS;
    2702             :         }
    2703             : 
    2704         478 :         if (ZCG(enabled) == 0) {
    2705           0 :                 return SUCCESS ;
    2706             :         }
    2707             : 
    2708             : /********************************************/
    2709             : /* End of non-SHM dependent initializations */
    2710             : /********************************************/
    2711             : #ifdef HAVE_OPCACHE_FILE_CACHE
    2712         478 :         if (!ZCG(accel_directives).file_cache_only) {
    2713             : #else
    2714             :         if (1) {
    2715             : #endif
    2716         477 :                 switch (zend_shared_alloc_startup(ZCG(accel_directives).memory_consumption)) {
    2717             :                         case ALLOC_SUCCESS:
    2718         477 :                                 if (zend_accel_init_shm() == FAILURE) {
    2719           0 :                                         accel_startup_ok = 0;
    2720           0 :                                         return FAILURE;
    2721             :                                 }
    2722         477 :                                 break;
    2723             :                         case ALLOC_FAILURE:
    2724           0 :                                 accel_startup_ok = 0;
    2725           0 :                                 zend_accel_error(ACCEL_LOG_FATAL, "Failure to initialize shared memory structures - probably not enough shared memory.");
    2726           0 :                                 return SUCCESS;
    2727             :                         case SUCCESSFULLY_REATTACHED:
    2728           0 :                                 zend_shared_alloc_lock();
    2729           0 :                                 accel_shared_globals = (zend_accel_shared_globals *) ZSMMG(app_shared_globals);
    2730           0 :                                 orig_new_interned_string = zend_new_interned_string;
    2731           0 :                                 orig_interned_strings_snapshot = zend_interned_strings_snapshot;
    2732           0 :                                 orig_interned_strings_restore = zend_interned_strings_restore;
    2733             : 
    2734           0 :                                 zend_new_interned_string = accel_new_interned_string_for_php;
    2735           0 :                                 zend_interned_strings_snapshot = accel_interned_strings_snapshot_for_php;
    2736           0 :                                 zend_interned_strings_restore = accel_interned_strings_restore_for_php;
    2737             : #ifndef ZTS
    2738           0 :                                 accel_use_shm_interned_strings();
    2739             : #endif
    2740           0 :                                 zend_shared_alloc_unlock();
    2741           0 :                                 break;
    2742             :                         case FAILED_REATTACHED:
    2743           0 :                                 accel_startup_ok = 0;
    2744           0 :                                 zend_accel_error(ACCEL_LOG_FATAL, "Failure to initialize shared memory structures - can not reattach to exiting shared memory.");
    2745           0 :                                 return SUCCESS;
    2746             :                                 break;
    2747             : #if ENABLE_FILE_CACHE_FALLBACK
    2748             :                         case ALLOC_FALLBACK:
    2749             :                                 zend_shared_alloc_lock();
    2750             :                                 fallback_process = 1;
    2751             :                                 zend_accel_init_auto_globals();
    2752             :                                 zend_shared_alloc_unlock();
    2753             :                                 goto file_cache_fallback;
    2754             :                                 break;
    2755             : #endif
    2756             :                 }
    2757             : 
    2758             :                 /* from this point further, shared memory is supposed to be OK */
    2759             : 
    2760             :                 /* remeber the last restart time in the process memory */
    2761         477 :                 ZCG(last_restart_time) = ZCSG(last_restart_time);
    2762             : 
    2763             :                 /* Init auto-global strings */
    2764         477 :                 zend_accel_init_auto_globals();
    2765             : 
    2766         477 :                 zend_shared_alloc_lock();
    2767         477 :                 zend_shared_alloc_save_state();
    2768         477 :                 zend_shared_alloc_unlock();
    2769             : 
    2770         477 :                 SHM_PROTECT();
    2771             : #ifdef HAVE_OPCACHE_FILE_CACHE
    2772           1 :         } else if (!ZCG(accel_directives).file_cache) {
    2773           0 :                 accel_startup_ok = 0;
    2774           0 :                 zend_accel_error(ACCEL_LOG_FATAL, "opcache.file_cache_only is set without a proper setting of opcache.file_cache");
    2775           0 :                 return SUCCESS;
    2776             :         } else {
    2777           1 :                 accel_shared_globals = calloc(1, sizeof(zend_accel_shared_globals));
    2778             : 
    2779             :                 /* Init auto-global strings */
    2780           1 :                 zend_accel_init_auto_globals();
    2781             : #endif
    2782             :         }
    2783             : #if ENABLE_FILE_CACHE_FALLBACK
    2784             : file_cache_fallback:
    2785             : #endif
    2786             : 
    2787             :         /* Override compiler */
    2788         478 :         accelerator_orig_compile_file = zend_compile_file;
    2789         478 :         zend_compile_file = persistent_compile_file;
    2790             : 
    2791             :         /* Override stream opener function (to eliminate open() call caused by
    2792             :          * include/require statements ) */
    2793         478 :         accelerator_orig_zend_stream_open_function = zend_stream_open_function;
    2794         478 :         zend_stream_open_function = persistent_stream_open_function;
    2795             : 
    2796             :         /* Override path resolver function (to eliminate stat() calls caused by
    2797             :          * include_once/require_once statements */
    2798         478 :         accelerator_orig_zend_resolve_path = zend_resolve_path;
    2799         478 :         zend_resolve_path = persistent_zend_resolve_path;
    2800             : 
    2801             :         /* Override chdir() function */
    2802        1434 :         if ((func = zend_hash_str_find_ptr(CG(function_table), "chdir", sizeof("chdir")-1)) != NULL &&
    2803         478 :             func->type == ZEND_INTERNAL_FUNCTION) {
    2804         478 :                 orig_chdir = func->internal_function.handler;
    2805         478 :                 func->internal_function.handler = ZEND_FN(accel_chdir);
    2806             :         }
    2807         478 :         ZCG(cwd) = NULL;
    2808         478 :         ZCG(include_path) = NULL;
    2809             : 
    2810             :         /* Override "include_path" modifier callback */
    2811         956 :         if ((ini_entry = zend_hash_str_find_ptr(EG(ini_directives), "include_path", sizeof("include_path")-1)) != NULL) {
    2812         478 :                 ZCG(include_path) = ini_entry->value;
    2813         478 :                 orig_include_path_on_modify = ini_entry->on_modify;
    2814         478 :                 ini_entry->on_modify = accel_include_path_on_modify;
    2815             :         }
    2816             : 
    2817         478 :         accel_startup_ok = 1;
    2818             : 
    2819             :         /* Override file_exists(), is_file() and is_readable() */
    2820         478 :         zend_accel_override_file_functions();
    2821             : 
    2822             :         /* Load black list */
    2823         478 :         accel_blacklist.entries = NULL;
    2824        1434 :         if (ZCG(enabled) && accel_startup_ok &&
    2825         478 :             ZCG(accel_directives).user_blacklist_filename &&
    2826         478 :             *ZCG(accel_directives.user_blacklist_filename)) {
    2827           3 :                 zend_accel_blacklist_init(&accel_blacklist);
    2828           3 :                 zend_accel_blacklist_load(&accel_blacklist, ZCG(accel_directives.user_blacklist_filename));
    2829             :         }
    2830             : 
    2831         478 :         zend_optimizer_startup();
    2832             : 
    2833         478 :         return SUCCESS;
    2834             : }
    2835             : 
    2836       23795 : static void accel_free_ts_resources()
    2837             : {
    2838             : #ifndef ZTS
    2839       23795 :         accel_globals_dtor(&accel_globals);
    2840             : #else
    2841             :         ts_free_id(accel_globals_id);
    2842             : #endif
    2843       23795 : }
    2844             : 
    2845       23795 : void accel_shutdown(void)
    2846             : {
    2847             :         zend_ini_entry *ini_entry;
    2848       23795 :         zend_bool file_cache_only = 0;
    2849             : 
    2850       23795 :         zend_optimizer_shutdown();
    2851             : 
    2852       23795 :         zend_accel_blacklist_shutdown(&accel_blacklist);
    2853             : 
    2854       23795 :         if (!ZCG(enabled) || !accel_startup_ok) {
    2855       23317 :                 accel_free_ts_resources();
    2856       23317 :                 return;
    2857             :         }
    2858             : 
    2859         478 :         if (ZCG(accel_directives).interned_strings_buffer) {
    2860             : #ifndef ZTS
    2861         476 :                 zend_hash_clean(CG(auto_globals));
    2862         476 :                 zend_hash_clean(CG(function_table));
    2863         476 :                 zend_hash_clean(CG(class_table));
    2864         476 :                 zend_hash_clean(EG(zend_constants));
    2865             : #endif
    2866             :         }
    2867             : 
    2868         478 :         accel_reset_pcre_cache();
    2869             : 
    2870         478 :         zend_new_interned_string = orig_new_interned_string;
    2871         478 :         zend_interned_strings_snapshot = orig_interned_strings_snapshot;
    2872         478 :         zend_interned_strings_restore = orig_interned_strings_restore;
    2873             : 
    2874             : #ifdef HAVE_OPCACHE_FILE_CACHE
    2875         478 :         file_cache_only = ZCG(accel_directives).file_cache_only;
    2876             : #endif
    2877             : 
    2878         478 :         accel_free_ts_resources();
    2879             : 
    2880         478 :         if (!file_cache_only) {
    2881         477 :                 zend_shared_alloc_shutdown();
    2882             :         }
    2883         478 :         zend_compile_file = accelerator_orig_compile_file;
    2884             : 
    2885         956 :         if ((ini_entry = zend_hash_str_find_ptr(EG(ini_directives), "include_path", sizeof("include_path")-1)) != NULL) {
    2886         478 :                 ini_entry->on_modify = orig_include_path_on_modify;
    2887             :         }
    2888             : }
    2889             : 
    2890           0 : void zend_accel_schedule_restart(zend_accel_restart_reason reason)
    2891             : {
    2892           0 :         if (ZCSG(restart_pending)) {
    2893             :                 /* don't schedule twice */
    2894           0 :                 return;
    2895             :         }
    2896           0 :         zend_accel_error(ACCEL_LOG_DEBUG, "Restart Scheduled!");
    2897             : 
    2898           0 :         HANDLE_BLOCK_INTERRUPTIONS();
    2899           0 :         SHM_UNPROTECT();
    2900           0 :         ZCSG(restart_pending) = 1;
    2901           0 :         ZCSG(restart_reason) = reason;
    2902           0 :         ZCSG(cache_status_before_restart) = ZCSG(accelerator_enabled);
    2903           0 :         ZCSG(accelerator_enabled) = 0;
    2904             : 
    2905           0 :         if (ZCG(accel_directives).force_restart_timeout) {
    2906           0 :                 ZCSG(force_restart_time) = zend_accel_get_time() + ZCG(accel_directives).force_restart_timeout;
    2907             :         } else {
    2908           0 :                 ZCSG(force_restart_time) = 0;
    2909             :         }
    2910           0 :         SHM_PROTECT();
    2911           0 :         HANDLE_UNBLOCK_INTERRUPTIONS();
    2912             : }
    2913             : 
    2914             : /* this is needed because on WIN32 lock is not decreased unless ZCG(counted) is set */
    2915             : #ifdef ZEND_WIN32
    2916             : #define accel_deactivate_now() ZCG(counted) = 1; accel_deactivate_sub()
    2917             : #else
    2918             : #define accel_deactivate_now() accel_deactivate_sub()
    2919             : #endif
    2920             : 
    2921             : /* ensures it is OK to read SHM
    2922             :         if it's not OK (restart in progress) returns FAILURE
    2923             :         if OK returns SUCCESS
    2924             :         MUST call accelerator_shm_read_unlock after done lock operations
    2925             : */
    2926           4 : int accelerator_shm_read_lock(void)
    2927             : {
    2928           4 :         if (ZCG(counted)) {
    2929             :                 /* counted means we are holding read lock for SHM, so that nothing bad can happen */
    2930           4 :                 return SUCCESS;
    2931             :         } else {
    2932             :                 /* here accelerator is active but we do not hold SHM lock. This means restart was scheduled
    2933             :                         or is in progress now */
    2934           0 :                 if (accel_activate_add() == FAILURE) { /* acquire usage lock */
    2935           0 :                         return FAILURE;
    2936             :                 }
    2937             :                 /* Now if we weren't inside restart, restart would not begin until we remove usage lock */
    2938           0 :                 if (ZCSG(restart_in_progress)) {
    2939             :                         /* we already were inside restart this means it's not safe to touch shm */
    2940           0 :                         accel_deactivate_now(); /* drop usage lock */
    2941           0 :                         return FAILURE;
    2942             :                 }
    2943           0 :                 ZCG(counted) = 1;
    2944             :         }
    2945           0 :         return SUCCESS;
    2946             : }
    2947             : 
    2948             : /* must be called ONLY after SUCCESSFUL accelerator_shm_read_lock */
    2949           3 : void accelerator_shm_read_unlock(void)
    2950             : {
    2951           3 :         if (!ZCG(counted)) {
    2952             :                 /* counted is 0 - meaning we had to readlock manually, release readlock now */
    2953           0 :                 accel_deactivate_now();
    2954             :         }
    2955           3 : }
    2956             : 
    2957             : ZEND_EXT_API zend_extension zend_extension_entry = {
    2958             :         ACCELERATOR_PRODUCT_NAME,               /* name */
    2959             :         PHP_VERSION,                                                    /* version */
    2960             :         "Zend Technologies",                                  /* author */
    2961             :         "http://www.zend.com/",                                       /* URL */
    2962             :         "Copyright (c) 1999-2016",                            /* copyright */
    2963             :         accel_startup,                                                  /* startup */
    2964             :         NULL,                                                                   /* shutdown */
    2965             :         accel_activate,                                                 /* per-script activation */
    2966             :         accel_deactivate,                                               /* per-script deactivation */
    2967             :         NULL,                                                                   /* message handler */
    2968             :         NULL,                                                                   /* op_array handler */
    2969             :         NULL,                                                                   /* extended statement handler */
    2970             :         NULL,                                                                   /* extended fcall begin handler */
    2971             :         NULL,                                                                   /* extended fcall end handler */
    2972             :         NULL,                                                                   /* op_array ctor */
    2973             :         NULL,                                                                   /* op_array dtor */
    2974             :         STANDARD_ZEND_EXTENSION_PROPERTIES
    2975             : };

Generated by: LCOV version 1.10

Generated at Tue, 27 Sep 2016 10:26:01 +0000 (4 days ago)

Copyright © 2005-2016 The PHP Group
All rights reserved.