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: 624 1195 52.2 %
Date: 2014-07-21 Functions: 36 60 60.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10

Generated at Tue, 22 Jul 2014 01:33:14 +0000 (2 days ago)

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