123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168 |
- /*
- +----------------------------------------------------------------------+
- | Zend OPcache |
- +----------------------------------------------------------------------+
- | Copyright (c) 1998-2018 The PHP Group |
- +----------------------------------------------------------------------+
- | This source file is subject to version 3.01 of the PHP license, |
- | that is bundled with this package in the file LICENSE, and is |
- | available through the world-wide-web at the following url: |
- | http://www.php.net/license/3_01.txt |
- | If you did not receive a copy of the PHP license and are unable to |
- | obtain it through the world-wide-web, please send a note to |
- | license@php.net so we can mail you a copy immediately. |
- +----------------------------------------------------------------------+
- | Authors: Andi Gutmans <andi@php.net> |
- | Zeev Suraski <zeev@php.net> |
- | Stanislav Malyshev <stas@zend.com> |
- | Dmitry Stogov <dmitry@php.net> |
- +----------------------------------------------------------------------+
- */
- #include "main/php.h"
- #include "main/php_globals.h"
- #include "zend.h"
- #include "zend_extensions.h"
- #include "zend_compile.h"
- #include "ZendAccelerator.h"
- #include "zend_persist.h"
- #include "zend_shared_alloc.h"
- #include "zend_accelerator_module.h"
- #include "zend_accelerator_blacklist.h"
- #include "zend_list.h"
- #include "zend_execute.h"
- #include "main/SAPI.h"
- #include "main/php_streams.h"
- #include "main/php_open_temporary_file.h"
- #include "zend_API.h"
- #include "zend_ini.h"
- #include "zend_virtual_cwd.h"
- #include "zend_accelerator_util_funcs.h"
- #include "zend_accelerator_hash.h"
- #include "ext/pcre/php_pcre.h"
- #include "ext/standard/md5.h"
- #ifdef HAVE_OPCACHE_FILE_CACHE
- # include "zend_file_cache.h"
- #endif
- #ifndef ZEND_WIN32
- #include <netdb.h>
- #endif
- #ifdef ZEND_WIN32
- typedef int uid_t;
- typedef int gid_t;
- #include <io.h>
- #endif
- #ifndef ZEND_WIN32
- # include <sys/time.h>
- #else
- # include <process.h>
- #endif
- #ifdef HAVE_UNISTD_H
- # include <unistd.h>
- #endif
- #include <fcntl.h>
- #include <signal.h>
- #include <time.h>
- #ifndef ZEND_WIN32
- # include <sys/types.h>
- # include <sys/ipc.h>
- #endif
- #include <sys/stat.h>
- #include <errno.h>
- #ifdef __AVX__
- #include <immintrin.h>
- #endif
- #define SHM_PROTECT() \
- do { \
- if (ZCG(accel_directives).protect_memory) { \
- zend_accel_shared_protect(1); \
- } \
- } while (0)
- #define SHM_UNPROTECT() \
- do { \
- if (ZCG(accel_directives).protect_memory) { \
- zend_accel_shared_protect(0); \
- } \
- } while (0)
- ZEND_EXTENSION();
- #ifndef ZTS
- zend_accel_globals accel_globals;
- #else
- int accel_globals_id;
- #if defined(COMPILE_DL_OPCACHE)
- ZEND_TSRMLS_CACHE_DEFINE()
- #endif
- #endif
- /* Points to the structure shared across all PHP processes */
- zend_accel_shared_globals *accel_shared_globals = NULL;
- /* true globals, no need for thread safety */
- zend_bool accel_startup_ok = 0;
- static char *zps_failure_reason = NULL;
- char *zps_api_failure_reason = NULL;
- #ifdef HAVE_OPCACHE_FILE_CACHE
- zend_bool file_cache_only = 0; /* process uses file cache only */
- #endif
- #if ENABLE_FILE_CACHE_FALLBACK
- zend_bool fallback_process = 0; /* process uses file cache fallback */
- #endif
- static zend_op_array *(*accelerator_orig_compile_file)(zend_file_handle *file_handle, int type);
- static int (*accelerator_orig_zend_stream_open_function)(const char *filename, zend_file_handle *handle );
- static zend_string *(*accelerator_orig_zend_resolve_path)(const char *filename, size_t filename_len);
- static zif_handler orig_chdir = NULL;
- static ZEND_INI_MH((*orig_include_path_on_modify)) = NULL;
- static int (*orig_post_startup_cb)(void);
- static void accel_gen_system_id(void);
- static int accel_post_startup(void);
- #ifdef ZEND_WIN32
- # define INCREMENT(v) InterlockedIncrement64(&ZCSG(v))
- # define DECREMENT(v) InterlockedDecrement64(&ZCSG(v))
- # define LOCKVAL(v) (ZCSG(v))
- #endif
- #ifdef ZEND_WIN32
- static time_t zend_accel_get_time(void)
- {
- FILETIME now;
- GetSystemTimeAsFileTime(&now);
- return (time_t) ((((((__int64)now.dwHighDateTime) << 32)|now.dwLowDateTime) - 116444736000000000L)/10000000);
- }
- #else
- # define zend_accel_get_time() time(NULL)
- #endif
- static inline int is_stream_path(const char *filename)
- {
- const char *p;
- for (p = filename;
- (*p >= 'a' && *p <= 'z') ||
- (*p >= 'A' && *p <= 'Z') ||
- (*p >= '0' && *p <= '9') ||
- *p == '+' || *p == '-' || *p == '.';
- p++);
- return ((p != filename) && (p[0] == ':') && (p[1] == '/') && (p[2] == '/'));
- }
- static inline int is_cacheable_stream_path(const char *filename)
- {
- return memcmp(filename, "file://", sizeof("file://") - 1) == 0 ||
- memcmp(filename, "phar://", sizeof("phar://") - 1) == 0;
- }
- /* O+ overrides PHP chdir() function and remembers the current working directory
- * in ZCG(cwd) and ZCG(cwd_len). Later accel_getcwd() can use stored value and
- * avoid getcwd() call.
- */
- static ZEND_FUNCTION(accel_chdir)
- {
- char cwd[MAXPATHLEN];
- orig_chdir(INTERNAL_FUNCTION_PARAM_PASSTHRU);
- if (VCWD_GETCWD(cwd, MAXPATHLEN)) {
- if (ZCG(cwd)) {
- zend_string_release_ex(ZCG(cwd), 0);
- }
- ZCG(cwd) = zend_string_init(cwd, strlen(cwd), 0);
- } else {
- if (ZCG(cwd)) {
- zend_string_release_ex(ZCG(cwd), 0);
- ZCG(cwd) = NULL;
- }
- }
- ZCG(cwd_key_len) = 0;
- ZCG(cwd_check) = 1;
- }
- static inline zend_string* accel_getcwd(void)
- {
- if (ZCG(cwd)) {
- return ZCG(cwd);
- } else {
- char cwd[MAXPATHLEN + 1];
- if (!VCWD_GETCWD(cwd, MAXPATHLEN)) {
- return NULL;
- }
- ZCG(cwd) = zend_string_init(cwd, strlen(cwd), 0);
- ZCG(cwd_key_len) = 0;
- ZCG(cwd_check) = 1;
- return ZCG(cwd);
- }
- }
- void zend_accel_schedule_restart_if_necessary(zend_accel_restart_reason reason)
- {
- if ((((double) ZSMMG(wasted_shared_memory)) / ZCG(accel_directives).memory_consumption) >= ZCG(accel_directives).max_wasted_percentage) {
- zend_accel_schedule_restart(reason);
- }
- }
- /* O+ tracks changes of "include_path" directive. It stores all the requested
- * values in ZCG(include_paths) shared hash table, current value in
- * ZCG(include_path)/ZCG(include_path_len) and one letter "path key" in
- * ZCG(include_path_key).
- */
- static ZEND_INI_MH(accel_include_path_on_modify)
- {
- int ret = orig_include_path_on_modify(entry, new_value, mh_arg1, mh_arg2, mh_arg3, stage);
- if (ret == SUCCESS) {
- ZCG(include_path) = new_value;
- ZCG(include_path_key_len) = 0;
- ZCG(include_path_check) = 1;
- }
- return ret;
- }
- static inline void accel_restart_enter(void)
- {
- #ifdef ZEND_WIN32
- INCREMENT(restart_in);
- #else
- struct flock restart_in_progress;
- restart_in_progress.l_type = F_WRLCK;
- restart_in_progress.l_whence = SEEK_SET;
- restart_in_progress.l_start = 2;
- restart_in_progress.l_len = 1;
- if (fcntl(lock_file, F_SETLK, &restart_in_progress) == -1) {
- zend_accel_error(ACCEL_LOG_DEBUG, "RestartC(+1): %s (%d)", strerror(errno), errno);
- }
- #endif
- ZCSG(restart_in_progress) = 1;
- }
- static inline void accel_restart_leave(void)
- {
- #ifdef ZEND_WIN32
- ZCSG(restart_in_progress) = 0;
- DECREMENT(restart_in);
- #else
- struct flock restart_finished;
- restart_finished.l_type = F_UNLCK;
- restart_finished.l_whence = SEEK_SET;
- restart_finished.l_start = 2;
- restart_finished.l_len = 1;
- ZCSG(restart_in_progress) = 0;
- if (fcntl(lock_file, F_SETLK, &restart_finished) == -1) {
- zend_accel_error(ACCEL_LOG_DEBUG, "RestartC(-1): %s (%d)", strerror(errno), errno);
- }
- #endif
- }
- static inline int accel_restart_is_active(void)
- {
- if (ZCSG(restart_in_progress)) {
- #ifndef ZEND_WIN32
- struct flock restart_check;
- restart_check.l_type = F_WRLCK;
- restart_check.l_whence = SEEK_SET;
- restart_check.l_start = 2;
- restart_check.l_len = 1;
- if (fcntl(lock_file, F_GETLK, &restart_check) == -1) {
- zend_accel_error(ACCEL_LOG_DEBUG, "RestartC: %s (%d)", strerror(errno), errno);
- return FAILURE;
- }
- if (restart_check.l_type == F_UNLCK) {
- ZCSG(restart_in_progress) = 0;
- return 0;
- } else {
- return 1;
- }
- #else
- return LOCKVAL(restart_in) != 0;
- #endif
- }
- return 0;
- }
- /* Creates a read lock for SHM access */
- static inline int accel_activate_add(void)
- {
- #ifdef ZEND_WIN32
- INCREMENT(mem_usage);
- #else
- struct flock mem_usage_lock;
- mem_usage_lock.l_type = F_RDLCK;
- mem_usage_lock.l_whence = SEEK_SET;
- mem_usage_lock.l_start = 1;
- mem_usage_lock.l_len = 1;
- if (fcntl(lock_file, F_SETLK, &mem_usage_lock) == -1) {
- zend_accel_error(ACCEL_LOG_DEBUG, "UpdateC(+1): %s (%d)", strerror(errno), errno);
- return FAILURE;
- }
- #endif
- return SUCCESS;
- }
- /* Releases a lock for SHM access */
- static inline void accel_deactivate_sub(void)
- {
- #ifdef ZEND_WIN32
- if (ZCG(counted)) {
- DECREMENT(mem_usage);
- ZCG(counted) = 0;
- }
- #else
- struct flock mem_usage_unlock;
- mem_usage_unlock.l_type = F_UNLCK;
- mem_usage_unlock.l_whence = SEEK_SET;
- mem_usage_unlock.l_start = 1;
- mem_usage_unlock.l_len = 1;
- if (fcntl(lock_file, F_SETLK, &mem_usage_unlock) == -1) {
- zend_accel_error(ACCEL_LOG_DEBUG, "UpdateC(-1): %s (%d)", strerror(errno), errno);
- }
- #endif
- }
- static inline void accel_unlock_all(void)
- {
- #ifdef ZEND_WIN32
- accel_deactivate_sub();
- #else
- struct flock mem_usage_unlock_all;
- mem_usage_unlock_all.l_type = F_UNLCK;
- mem_usage_unlock_all.l_whence = SEEK_SET;
- mem_usage_unlock_all.l_start = 0;
- mem_usage_unlock_all.l_len = 0;
- if (fcntl(lock_file, F_SETLK, &mem_usage_unlock_all) == -1) {
- zend_accel_error(ACCEL_LOG_DEBUG, "UnlockAll: %s (%d)", strerror(errno), errno);
- }
- #endif
- }
- /* Interned strings support */
- /* O+ disables creation of interned strings by regular PHP compiler, instead,
- * it creates interned strings in shared memory when saves a script.
- * Such interned strings are shared across all PHP processes
- */
- #define STRTAB_INVALID_POS 0
- #define STRTAB_HASH_TO_SLOT(tab, h) \
- ((uint32_t*)((char*)(tab) + sizeof(*(tab)) + ((h) & (tab)->nTableMask)))
- #define STRTAB_STR_TO_POS(tab, s) \
- ((uint32_t)((char*)s - (char*)(tab)))
- #define STRTAB_POS_TO_STR(tab, pos) \
- ((zend_string*)((char*)(tab) + (pos)))
- #define STRTAB_COLLISION(s) \
- (*((uint32_t*)((char*)s - sizeof(uint32_t))))
- #define STRTAB_STR_SIZE(s) \
- ZEND_MM_ALIGNED_SIZE_EX(_ZSTR_HEADER_SIZE + ZSTR_LEN(s) + 5, 8)
- #define STRTAB_NEXT(s) \
- ((zend_string*)((char*)(s) + STRTAB_STR_SIZE(s)))
- static void accel_interned_strings_restore_state(void)
- {
- zend_string *s, *top;
- uint32_t *hash_slot, n;
- /* clear removed content */
- memset(ZCSG(interned_strings).saved_top,
- 0, (char*)ZCSG(interned_strings).top - (char*)ZCSG(interned_strings).saved_top);
- /* Reset "top" */
- ZCSG(interned_strings).top = ZCSG(interned_strings).saved_top;
- /* rehash */
- memset((char*)&ZCSG(interned_strings) + sizeof(zend_string_table),
- STRTAB_INVALID_POS,
- (char*)ZCSG(interned_strings).start -
- ((char*)&ZCSG(interned_strings) + sizeof(zend_string_table)));
- s = ZCSG(interned_strings).start;
- top = ZCSG(interned_strings).top;
- n = 0;
- if (EXPECTED(s < top)) {
- do {
- hash_slot = STRTAB_HASH_TO_SLOT(&ZCSG(interned_strings), ZSTR_H(s));
- STRTAB_COLLISION(s) = *hash_slot;
- *hash_slot = STRTAB_STR_TO_POS(&ZCSG(interned_strings), s);
- s = STRTAB_NEXT(s);
- n++;
- } while (s < top);
- }
- ZCSG(interned_strings).nNumOfElements = n;
- }
- static void accel_interned_strings_save_state(void)
- {
- ZCSG(interned_strings).saved_top = ZCSG(interned_strings).top;
- }
- static zend_always_inline zend_string *accel_find_interned_string(zend_string *str)
- {
- /* for now interned strings are supported only for non-ZTS build */
- zend_ulong h;
- uint32_t pos;
- zend_string *s;
- if (IS_ACCEL_INTERNED(str)) {
- /* this is already an interned string */
- return str;
- }
- if (!ZCG(counted)) {
- if (!ZCG(accelerator_enabled) || accel_activate_add() == FAILURE) {
- return NULL;
- }
- ZCG(counted) = 1;
- }
- h = zend_string_hash_val(str);
- /* check for existing interned string */
- pos = *STRTAB_HASH_TO_SLOT(&ZCSG(interned_strings), h);
- if (EXPECTED(pos != STRTAB_INVALID_POS)) {
- do {
- s = STRTAB_POS_TO_STR(&ZCSG(interned_strings), pos);
- if (EXPECTED(ZSTR_H(s) == h) && zend_string_equal_content(s, str)) {
- return s;
- }
- pos = STRTAB_COLLISION(s);
- } while (pos != STRTAB_INVALID_POS);
- }
- return NULL;
- }
- zend_string* ZEND_FASTCALL accel_new_interned_string(zend_string *str)
- {
- zend_ulong h;
- uint32_t pos, *hash_slot;
- zend_string *s;
- #ifdef HAVE_OPCACHE_FILE_CACHE
- if (UNEXPECTED(file_cache_only)) {
- return str;
- }
- #endif
- if (IS_ACCEL_INTERNED(str)) {
- /* this is already an interned string */
- return str;
- }
- h = zend_string_hash_val(str);
- /* check for existing interned string */
- hash_slot = STRTAB_HASH_TO_SLOT(&ZCSG(interned_strings), h);
- pos = *hash_slot;
- if (EXPECTED(pos != STRTAB_INVALID_POS)) {
- do {
- s = STRTAB_POS_TO_STR(&ZCSG(interned_strings), pos);
- if (EXPECTED(ZSTR_H(s) == h) && zend_string_equal_content(s, str)) {
- zend_string_release(str);
- return s;
- }
- pos = STRTAB_COLLISION(s);
- } while (pos != STRTAB_INVALID_POS);
- }
- if (UNEXPECTED((char*)ZCSG(interned_strings).end - (char*)ZCSG(interned_strings).top < STRTAB_STR_SIZE(str))) {
- /* no memory, return the same non-interned string */
- zend_accel_error(ACCEL_LOG_WARNING, "Interned string buffer overflow");
- return str;
- }
- /* create new interning string in shared interned strings buffer */
- ZCSG(interned_strings).nNumOfElements++;
- s = ZCSG(interned_strings).top;
- hash_slot = STRTAB_HASH_TO_SLOT(&ZCSG(interned_strings), h);
- STRTAB_COLLISION(s) = *hash_slot;
- *hash_slot = STRTAB_STR_TO_POS(&ZCSG(interned_strings), s);
- GC_SET_REFCOUNT(s, 1);
- GC_TYPE_INFO(s) = IS_STRING | ((IS_STR_INTERNED | IS_STR_PERMANENT) << GC_FLAGS_SHIFT);
- ZSTR_H(s) = h;
- ZSTR_LEN(s) = ZSTR_LEN(str);
- memcpy(ZSTR_VAL(s), ZSTR_VAL(str), ZSTR_LEN(s) + 1);
- ZCSG(interned_strings).top = STRTAB_NEXT(s);
- zend_string_release(str);
- return s;
- }
- static zend_string* ZEND_FASTCALL accel_new_interned_string_for_php(zend_string *str)
- {
- zend_string_hash_val(str);
- if (ZCG(counted)) {
- zend_string *ret = accel_find_interned_string(str);
- if (ret) {
- zend_string_release(str);
- return ret;
- }
- }
- return str;
- }
- static zend_always_inline zend_string *accel_find_interned_string_ex(zend_ulong h, const char *str, size_t size)
- {
- uint32_t pos;
- zend_string *s;
- /* check for existing interned string */
- pos = *STRTAB_HASH_TO_SLOT(&ZCSG(interned_strings), h);
- if (EXPECTED(pos != STRTAB_INVALID_POS)) {
- do {
- s = STRTAB_POS_TO_STR(&ZCSG(interned_strings), pos);
- if (EXPECTED(ZSTR_H(s) == h) && EXPECTED(ZSTR_LEN(s) == size)) {
- if (!memcmp(ZSTR_VAL(s), str, size)) {
- return s;
- }
- }
- pos = STRTAB_COLLISION(s);
- } while (pos != STRTAB_INVALID_POS);
- }
- return NULL;
- }
- static zend_string* ZEND_FASTCALL accel_init_interned_string_for_php(const char *str, size_t size, int permanent)
- {
- if (ZCG(counted)) {
- zend_ulong h = zend_inline_hash_func(str, size);
- zend_string *ret = accel_find_interned_string_ex(h, str, size);
- if (!ret) {
- ret = zend_string_init(str, size, permanent);
- ZSTR_H(ret) = h;
- }
- return ret;
- }
- return zend_string_init(str, size, permanent);
- }
- /* Copy PHP interned strings from PHP process memory into the shared memory */
- static void accel_copy_permanent_strings(zend_new_interned_string_func_t new_interned_string)
- {
- uint32_t j;
- Bucket *p, *q;
- HashTable *ht;
- /* empty string */
- zend_empty_string = new_interned_string(zend_empty_string);
- for (j = 0; j < 256; j++) {
- zend_one_char_string[j] = new_interned_string(ZSTR_CHAR(j));
- }
- for (j = 0; j < ZEND_STR_LAST_KNOWN; j++) {
- zend_known_strings[j] = new_interned_string(zend_known_strings[j]);
- }
- /* function table hash keys */
- ZEND_HASH_FOREACH_BUCKET(CG(function_table), p) {
- if (p->key) {
- p->key = new_interned_string(p->key);
- }
- if (Z_FUNC(p->val)->common.function_name) {
- Z_FUNC(p->val)->common.function_name = new_interned_string(Z_FUNC(p->val)->common.function_name);
- }
- if (Z_FUNC(p->val)->common.arg_info &&
- (Z_FUNC(p->val)->common.fn_flags & (ZEND_ACC_HAS_RETURN_TYPE|ZEND_ACC_HAS_TYPE_HINTS))) {
- uint32_t i;
- uint32_t num_args = Z_FUNC(p->val)->common.num_args + 1;
- zend_arg_info *arg_info = Z_FUNC(p->val)->common.arg_info - 1;
- if (Z_FUNC(p->val)->common.fn_flags & ZEND_ACC_VARIADIC) {
- num_args++;
- }
- for (i = 0 ; i < num_args; i++) {
- if (ZEND_TYPE_IS_CLASS(arg_info[i].type)) {
- zend_bool allow_null = ZEND_TYPE_ALLOW_NULL(arg_info[i].type);
- arg_info[i].type = ZEND_TYPE_ENCODE_CLASS(new_interned_string(ZEND_TYPE_NAME(arg_info[i].type)), allow_null);
- }
- }
- }
- } ZEND_HASH_FOREACH_END();
- /* class table hash keys, class names, properties, methods, constants, etc */
- ZEND_HASH_FOREACH_BUCKET(CG(class_table), p) {
- zend_class_entry *ce;
- ce = (zend_class_entry*)Z_PTR(p->val);
- if (p->key) {
- p->key = new_interned_string(p->key);
- }
- if (ce->name) {
- ce->name = new_interned_string(ce->name);
- }
- ZEND_HASH_FOREACH_BUCKET(&ce->properties_info, q) {
- zend_property_info *info;
- info = (zend_property_info*)Z_PTR(q->val);
- if (q->key) {
- q->key = new_interned_string(q->key);
- }
- if (info->name) {
- info->name = new_interned_string(info->name);
- }
- } ZEND_HASH_FOREACH_END();
- ZEND_HASH_FOREACH_BUCKET(&ce->function_table, q) {
- if (q->key) {
- q->key = new_interned_string(q->key);
- }
- if (Z_FUNC(q->val)->common.function_name) {
- Z_FUNC(q->val)->common.function_name = new_interned_string(Z_FUNC(q->val)->common.function_name);
- }
- } ZEND_HASH_FOREACH_END();
- ZEND_HASH_FOREACH_BUCKET(&ce->constants_table, q) {
- if (q->key) {
- q->key = new_interned_string(q->key);
- }
- } ZEND_HASH_FOREACH_END();
- } ZEND_HASH_FOREACH_END();
- /* constant hash keys */
- ZEND_HASH_FOREACH_BUCKET(EG(zend_constants), p) {
- zend_constant *c;
- if (p->key) {
- p->key = new_interned_string(p->key);
- }
- c = (zend_constant*)Z_PTR(p->val);
- if (c->name) {
- c->name = new_interned_string(c->name);
- }
- if (Z_TYPE(c->value) == IS_STRING) {
- ZVAL_STR(&c->value, new_interned_string(Z_STR(c->value)));
- }
- } ZEND_HASH_FOREACH_END();
- /* auto globals hash keys and names */
- ZEND_HASH_FOREACH_BUCKET(CG(auto_globals), p) {
- zend_auto_global *auto_global;
- auto_global = (zend_auto_global*)Z_PTR(p->val);
- zend_string_addref(auto_global->name);
- auto_global->name = new_interned_string(auto_global->name);
- if (p->key) {
- p->key = new_interned_string(p->key);
- }
- } ZEND_HASH_FOREACH_END();
- ZEND_HASH_FOREACH_BUCKET(&module_registry, p) {
- if (p->key) {
- p->key = new_interned_string(p->key);
- }
- } ZEND_HASH_FOREACH_END();
- ZEND_HASH_FOREACH_BUCKET(EG(ini_directives), p) {
- zend_ini_entry *entry = (zend_ini_entry*)Z_PTR(p->val);
- if (p->key) {
- p->key = new_interned_string(p->key);
- }
- if (entry->name) {
- entry->name = new_interned_string(entry->name);
- }
- if (entry->value) {
- entry->value = new_interned_string(entry->value);
- }
- if (entry->orig_value) {
- entry->orig_value = new_interned_string(entry->orig_value);
- }
- } ZEND_HASH_FOREACH_END();
- ht = php_get_stream_filters_hash_global();
- ZEND_HASH_FOREACH_BUCKET(ht, p) {
- if (p->key) {
- p->key = new_interned_string(p->key);
- }
- } ZEND_HASH_FOREACH_END();
- ht = php_stream_get_url_stream_wrappers_hash_global();
- ZEND_HASH_FOREACH_BUCKET(ht, p) {
- if (p->key) {
- p->key = new_interned_string(p->key);
- }
- } ZEND_HASH_FOREACH_END();
- ht = php_stream_xport_get_hash();
- ZEND_HASH_FOREACH_BUCKET(ht, p) {
- if (p->key) {
- p->key = new_interned_string(p->key);
- }
- } ZEND_HASH_FOREACH_END();
- }
- static zend_string* ZEND_FASTCALL accel_replace_string_by_shm_permanent(zend_string *str)
- {
- zend_string *ret = accel_find_interned_string(str);
- if (ret) {
- zend_string_release(str);
- return ret;
- }
- return str;
- }
- static zend_string* ZEND_FASTCALL accel_replace_string_by_process_permanent(zend_string *str)
- {
- zend_string *ret = zend_interned_string_find_permanent(str);
- if (ret) {
- zend_string_release(str);
- return ret;
- }
- ZEND_ASSERT(!IS_ACCEL_INTERNED(str));
- return str;
- }
- static void accel_use_shm_interned_strings(void)
- {
- HANDLE_BLOCK_INTERRUPTIONS();
- SHM_UNPROTECT();
- zend_shared_alloc_lock();
- if (ZCSG(interned_strings).saved_top == NULL) {
- accel_copy_permanent_strings(accel_new_interned_string);
- } else {
- ZCG(counted) = 1;
- accel_copy_permanent_strings(accel_replace_string_by_shm_permanent);
- ZCG(counted) = 0;
- }
- accel_interned_strings_save_state();
- zend_shared_alloc_unlock();
- SHM_PROTECT();
- HANDLE_UNBLOCK_INTERRUPTIONS();
- }
- static void accel_use_permanent_interned_strings(void)
- {
- accel_copy_permanent_strings(accel_replace_string_by_process_permanent);
- }
- #ifndef ZEND_WIN32
- static inline void kill_all_lockers(struct flock *mem_usage_check)
- {
- int success, tries;
- /* so that other process won't try to force while we are busy cleaning up */
- ZCSG(force_restart_time) = 0;
- while (mem_usage_check->l_pid > 0) {
- /* Clear previous errno, reset success and tries */
- errno = 0;
- success = 0;
- tries = 10;
- while (tries--) {
- zend_accel_error(ACCEL_LOG_WARNING, "Attempting to kill locker %d", mem_usage_check->l_pid);
- if (kill(mem_usage_check->l_pid, SIGKILL)) {
- if (errno == ESRCH) {
- /* Process died before the signal was sent */
- success = 1;
- zend_accel_error(ACCEL_LOG_WARNING, "Process %d died before SIGKILL was sent", mem_usage_check->l_pid);
- }
- break;
- }
- /* give it a chance to die */
- usleep(20000);
- if (kill(mem_usage_check->l_pid, 0)) {
- if (errno == ESRCH) {
- /* successfully killed locker, process no longer exists */
- success = 1;
- zend_accel_error(ACCEL_LOG_WARNING, "Killed locker %d", mem_usage_check->l_pid);
- }
- break;
- }
- usleep(10000);
- }
- if (!success) {
- /* errno is not ESRCH or we ran out of tries to kill the locker */
- ZCSG(force_restart_time) = time(NULL); /* restore forced restart request */
- /* cannot kill the locker, bail out with error */
- zend_accel_error(ACCEL_LOG_ERROR, "Cannot kill process %d: %s!", mem_usage_check->l_pid, strerror(errno));
- }
- mem_usage_check->l_type = F_WRLCK;
- mem_usage_check->l_whence = SEEK_SET;
- mem_usage_check->l_start = 1;
- mem_usage_check->l_len = 1;
- mem_usage_check->l_pid = -1;
- if (fcntl(lock_file, F_GETLK, mem_usage_check) == -1) {
- zend_accel_error(ACCEL_LOG_DEBUG, "KLockers: %s (%d)", strerror(errno), errno);
- break;
- }
- if (mem_usage_check->l_type == F_UNLCK || mem_usage_check->l_pid <= 0) {
- break;
- }
- }
- }
- #endif
- static inline int accel_is_inactive(void)
- {
- #ifdef ZEND_WIN32
- if (LOCKVAL(mem_usage) == 0) {
- return SUCCESS;
- }
- #else
- struct flock mem_usage_check;
- mem_usage_check.l_type = F_WRLCK;
- mem_usage_check.l_whence = SEEK_SET;
- mem_usage_check.l_start = 1;
- mem_usage_check.l_len = 1;
- mem_usage_check.l_pid = -1;
- if (fcntl(lock_file, F_GETLK, &mem_usage_check) == -1) {
- zend_accel_error(ACCEL_LOG_DEBUG, "UpdateC: %s (%d)", strerror(errno), errno);
- return FAILURE;
- }
- if (mem_usage_check.l_type == F_UNLCK) {
- return SUCCESS;
- }
- if (ZCG(accel_directives).force_restart_timeout
- && ZCSG(force_restart_time)
- && time(NULL) >= ZCSG(force_restart_time)) {
- zend_accel_error(ACCEL_LOG_WARNING, "Forced restart at %ld (after " ZEND_LONG_FMT " seconds), locked by %d", (long)time(NULL), ZCG(accel_directives).force_restart_timeout, mem_usage_check.l_pid);
- kill_all_lockers(&mem_usage_check);
- return FAILURE; /* next request should be able to restart it */
- }
- #endif
- return FAILURE;
- }
- static int zend_get_stream_timestamp(const char *filename, zend_stat_t *statbuf)
- {
- php_stream_wrapper *wrapper;
- php_stream_statbuf stream_statbuf;
- int ret, er;
- if (!filename) {
- return FAILURE;
- }
- wrapper = php_stream_locate_url_wrapper(filename, NULL, STREAM_LOCATE_WRAPPERS_ONLY);
- if (!wrapper) {
- return FAILURE;
- }
- if (!wrapper->wops || !wrapper->wops->url_stat) {
- statbuf->st_mtime = 1;
- return SUCCESS; /* anything other than 0 is considered to be a valid timestamp */
- }
- er = EG(error_reporting);
- EG(error_reporting) = 0;
- zend_try {
- ret = wrapper->wops->url_stat(wrapper, (char*)filename, PHP_STREAM_URL_STAT_QUIET, &stream_statbuf, NULL);
- } zend_catch {
- ret = -1;
- } zend_end_try();
- EG(error_reporting) = er;
- if (ret != 0) {
- return FAILURE;
- }
- *statbuf = stream_statbuf.sb;
- return SUCCESS;
- }
- #if ZEND_WIN32
- static accel_time_t zend_get_file_handle_timestamp_win(zend_file_handle *file_handle, size_t *size)
- {
- static unsigned __int64 utc_base = 0;
- static FILETIME utc_base_ft;
- WIN32_FILE_ATTRIBUTE_DATA fdata;
- if (!file_handle->opened_path) {
- return 0;
- }
- if (!utc_base) {
- SYSTEMTIME st;
- st.wYear = 1970;
- st.wMonth = 1;
- st.wDay = 1;
- st.wHour = 0;
- st.wMinute = 0;
- st.wSecond = 0;
- st.wMilliseconds = 0;
- SystemTimeToFileTime (&st, &utc_base_ft);
- utc_base = (((unsigned __int64)utc_base_ft.dwHighDateTime) << 32) + utc_base_ft.dwLowDateTime;
- }
- if (file_handle->opened_path && GetFileAttributesEx(file_handle->opened_path->val, GetFileExInfoStandard, &fdata) != 0) {
- unsigned __int64 ftime;
- if (CompareFileTime (&fdata.ftLastWriteTime, &utc_base_ft) < 0) {
- return 0;
- }
- ftime = (((unsigned __int64)fdata.ftLastWriteTime.dwHighDateTime) << 32) + fdata.ftLastWriteTime.dwLowDateTime - utc_base;
- ftime /= 10000000L;
- if (size) {
- *size = (size_t)((((unsigned __int64)fdata.nFileSizeHigh) << 32) + (unsigned __int64)fdata.nFileSizeLow);
- }
- return (accel_time_t)ftime;
- }
- return 0;
- }
- #endif
- accel_time_t zend_get_file_handle_timestamp(zend_file_handle *file_handle, size_t *size)
- {
- zend_stat_t statbuf;
- #ifdef ZEND_WIN32
- accel_time_t res;
- #endif
- if (sapi_module.get_stat &&
- !EG(current_execute_data) &&
- file_handle->filename == SG(request_info).path_translated) {
- zend_stat_t *tmpbuf = sapi_module.get_stat();
- if (tmpbuf) {
- if (size) {
- *size = tmpbuf->st_size;
- }
- return tmpbuf->st_mtime;
- }
- }
- #ifdef ZEND_WIN32
- res = zend_get_file_handle_timestamp_win(file_handle, size);
- if (res) {
- return res;
- }
- #endif
- switch (file_handle->type) {
- case ZEND_HANDLE_FD:
- if (zend_fstat(file_handle->handle.fd, &statbuf) == -1) {
- return 0;
- }
- break;
- case ZEND_HANDLE_FP:
- if (zend_fstat(fileno(file_handle->handle.fp), &statbuf) == -1) {
- if (zend_get_stream_timestamp(file_handle->filename, &statbuf) != SUCCESS) {
- return 0;
- }
- }
- break;
- case ZEND_HANDLE_FILENAME:
- case ZEND_HANDLE_MAPPED:
- if (file_handle->opened_path) {
- char *file_path = ZSTR_VAL(file_handle->opened_path);
- if (is_stream_path(file_path)) {
- if (zend_get_stream_timestamp(file_path, &statbuf) == SUCCESS) {
- break;
- }
- }
- if (VCWD_STAT(file_path, &statbuf) != -1) {
- break;
- }
- }
- if (zend_get_stream_timestamp(file_handle->filename, &statbuf) != SUCCESS) {
- return 0;
- }
- break;
- case ZEND_HANDLE_STREAM:
- {
- php_stream *stream = (php_stream *)file_handle->handle.stream.handle;
- php_stream_statbuf sb;
- int ret, er;
- if (!stream ||
- !stream->ops ||
- !stream->ops->stat) {
- return 0;
- }
- er = EG(error_reporting);
- EG(error_reporting) = 0;
- zend_try {
- ret = stream->ops->stat(stream, &sb);
- } zend_catch {
- ret = -1;
- } zend_end_try();
- EG(error_reporting) = er;
- if (ret != 0) {
- return 0;
- }
- statbuf = sb.sb;
- }
- break;
- default:
- return 0;
- }
- if (size) {
- *size = statbuf.st_size;
- }
- return statbuf.st_mtime;
- }
- static inline int do_validate_timestamps(zend_persistent_script *persistent_script, zend_file_handle *file_handle)
- {
- zend_file_handle ps_handle;
- zend_string *full_path_ptr = NULL;
- /** check that the persistent script is indeed the same file we cached
- * (if part of the path is a symlink than it possible that the user will change it)
- * See bug #15140
- */
- if (file_handle->opened_path) {
- if (persistent_script->script.filename != file_handle->opened_path &&
- !zend_string_equal_content(persistent_script->script.filename, file_handle->opened_path)) {
- return FAILURE;
- }
- } else {
- full_path_ptr = accelerator_orig_zend_resolve_path(file_handle->filename, strlen(file_handle->filename));
- if (full_path_ptr &&
- persistent_script->script.filename != full_path_ptr &&
- !zend_string_equal_content(persistent_script->script.filename, full_path_ptr)) {
- zend_string_release_ex(full_path_ptr, 0);
- return FAILURE;
- }
- file_handle->opened_path = full_path_ptr;
- }
- if (persistent_script->timestamp == 0) {
- if (full_path_ptr) {
- zend_string_release_ex(full_path_ptr, 0);
- file_handle->opened_path = NULL;
- }
- return FAILURE;
- }
- if (zend_get_file_handle_timestamp(file_handle, NULL) == persistent_script->timestamp) {
- if (full_path_ptr) {
- zend_string_release_ex(full_path_ptr, 0);
- file_handle->opened_path = NULL;
- }
- return SUCCESS;
- }
- if (full_path_ptr) {
- zend_string_release_ex(full_path_ptr, 0);
- file_handle->opened_path = NULL;
- }
- ps_handle.type = ZEND_HANDLE_FILENAME;
- ps_handle.filename = ZSTR_VAL(persistent_script->script.filename);
- ps_handle.opened_path = persistent_script->script.filename;
- if (zend_get_file_handle_timestamp(&ps_handle, NULL) == persistent_script->timestamp) {
- return SUCCESS;
- }
- return FAILURE;
- }
- int validate_timestamp_and_record(zend_persistent_script *persistent_script, zend_file_handle *file_handle)
- {
- if (ZCG(accel_directives).revalidate_freq &&
- persistent_script->dynamic_members.revalidate >= ZCG(request_time)) {
- return SUCCESS;
- } else if (do_validate_timestamps(persistent_script, file_handle) == FAILURE) {
- return FAILURE;
- } else {
- persistent_script->dynamic_members.revalidate = ZCG(request_time) + ZCG(accel_directives).revalidate_freq;
- return SUCCESS;
- }
- }
- int validate_timestamp_and_record_ex(zend_persistent_script *persistent_script, zend_file_handle *file_handle)
- {
- int ret;
- SHM_UNPROTECT();
- ret = validate_timestamp_and_record(persistent_script, file_handle);
- SHM_PROTECT();
- return ret;
- }
- /* Instead of resolving full real path name each time we need to identify file,
- * we create a key that consist from requested file name, current working
- * directory, current include_path, etc */
- char *accel_make_persistent_key(const char *path, size_t path_length, int *key_len)
- {
- int key_length;
- /* CWD and include_path don't matter for absolute file names and streams */
- if (IS_ABSOLUTE_PATH(path, path_length)) {
- /* pass */
- ZCG(key_len) = 0;
- } else if (UNEXPECTED(is_stream_path(path))) {
- if (!is_cacheable_stream_path(path)) {
- return NULL;
- }
- /* pass */
- ZCG(key_len) = 0;
- } else if (UNEXPECTED(!ZCG(accel_directives).use_cwd)) {
- /* pass */
- ZCG(key_len) = 0;
- } else {
- const char *include_path = NULL, *cwd = NULL;
- int include_path_len = 0, cwd_len = 0;
- zend_string *parent_script = NULL;
- size_t parent_script_len = 0;
- if (EXPECTED(ZCG(cwd_key_len))) {
- cwd = ZCG(cwd_key);
- cwd_len = ZCG(cwd_key_len);
- } else {
- zend_string *cwd_str = accel_getcwd();
- if (UNEXPECTED(!cwd_str)) {
- /* we don't handle this well for now. */
- zend_accel_error(ACCEL_LOG_INFO, "getcwd() failed for '%s' (%d), please try to set opcache.use_cwd to 0 in ini file", path, errno);
- return NULL;
- }
- cwd = ZSTR_VAL(cwd_str);
- cwd_len = ZSTR_LEN(cwd_str);
- if (ZCG(cwd_check)) {
- ZCG(cwd_check) = 0;
- if (ZCG(accelerator_enabled)) {
- zend_string *str = accel_find_interned_string(cwd_str);
- if (!str) {
- HANDLE_BLOCK_INTERRUPTIONS();
- SHM_UNPROTECT();
- zend_shared_alloc_lock();
- str = accel_new_interned_string(zend_string_copy(cwd_str));
- if (str == cwd_str) {
- zend_string_release_ex(str, 0);
- str = NULL;
- }
- zend_shared_alloc_unlock();
- SHM_PROTECT();
- HANDLE_UNBLOCK_INTERRUPTIONS();
- }
- if (str) {
- char buf[32];
- char *res = zend_print_long_to_buf(buf + sizeof(buf) - 1, STRTAB_STR_TO_POS(&ZCSG(interned_strings), str));
- cwd_len = ZCG(cwd_key_len) = buf + sizeof(buf) - 1 - res;
- cwd = ZCG(cwd_key);
- memcpy(ZCG(cwd_key), res, cwd_len + 1);
- } else {
- return NULL;
- }
- } else {
- return NULL;
- }
- }
- }
- if (EXPECTED(ZCG(include_path_key_len))) {
- include_path = ZCG(include_path_key);
- include_path_len = ZCG(include_path_key_len);
- } else if (!ZCG(include_path) || ZSTR_LEN(ZCG(include_path)) == 0) {
- include_path = "";
- include_path_len = 0;
- } else {
- include_path = ZSTR_VAL(ZCG(include_path));
- include_path_len = ZSTR_LEN(ZCG(include_path));
- if (ZCG(include_path_check)) {
- ZCG(include_path_check) = 0;
- if (ZCG(accelerator_enabled)) {
- zend_string *str = accel_find_interned_string(ZCG(include_path));
- if (!str) {
- HANDLE_BLOCK_INTERRUPTIONS();
- SHM_UNPROTECT();
- zend_shared_alloc_lock();
- str = accel_new_interned_string(zend_string_copy(ZCG(include_path)));
- if (str == ZCG(include_path)) {
- str = NULL;
- }
- zend_shared_alloc_unlock();
- SHM_PROTECT();
- HANDLE_UNBLOCK_INTERRUPTIONS();
- }
- if (str) {
- char buf[32];
- char *res = zend_print_long_to_buf(buf + sizeof(buf) - 1, STRTAB_STR_TO_POS(&ZCSG(interned_strings), str));
- include_path_len = ZCG(include_path_key_len) = buf + sizeof(buf) - 1 - res;
- include_path = ZCG(include_path_key);
- memcpy(ZCG(include_path_key), res, include_path_len + 1);
- } else {
- return NULL;
- }
- } else {
- return NULL;
- }
- }
- }
- /* Calculate key length */
- if (UNEXPECTED((size_t)(cwd_len + path_length + include_path_len + 2) >= sizeof(ZCG(key)))) {
- return NULL;
- }
- /* Generate key
- * Note - the include_path must be the last element in the key,
- * since in itself, it may include colons (which we use to separate
- * different components of the key)
- */
- memcpy(ZCG(key), path, path_length);
- ZCG(key)[path_length] = ':';
- key_length = path_length + 1;
- memcpy(ZCG(key) + key_length, cwd, cwd_len);
- key_length += cwd_len;
- if (include_path_len) {
- ZCG(key)[key_length] = ':';
- key_length += 1;
- memcpy(ZCG(key) + key_length, include_path, include_path_len);
- key_length += include_path_len;
- }
- /* Here we add to the key the parent script directory,
- * since fopen_wrappers from version 4.0.7 use current script's path
- * in include path too.
- */
- if (EXPECTED(EG(current_execute_data)) &&
- EXPECTED((parent_script = zend_get_executed_filename_ex()) != NULL)) {
- parent_script_len = ZSTR_LEN(parent_script);
- while ((--parent_script_len > 0) && !IS_SLASH(ZSTR_VAL(parent_script)[parent_script_len]));
- if (UNEXPECTED((size_t)(key_length + parent_script_len + 1) >= sizeof(ZCG(key)))) {
- return NULL;
- }
- ZCG(key)[key_length] = ':';
- key_length += 1;
- memcpy(ZCG(key) + key_length, ZSTR_VAL(parent_script), parent_script_len);
- key_length += parent_script_len;
- }
- ZCG(key)[key_length] = '\0';
- *key_len = ZCG(key_len) = key_length;
- return ZCG(key);
- }
- /* not use_cwd */
- *key_len = path_length;
- return (char*)path;
- }
- int zend_accel_invalidate(const char *filename, size_t filename_len, zend_bool force)
- {
- zend_string *realpath;
- zend_persistent_script *persistent_script;
- if (!ZCG(accelerator_enabled) || accelerator_shm_read_lock() != SUCCESS) {
- return FAILURE;
- }
- realpath = accelerator_orig_zend_resolve_path(filename, filename_len);
- if (!realpath) {
- return FAILURE;
- }
- #ifdef HAVE_OPCACHE_FILE_CACHE
- if (ZCG(accel_directives).file_cache) {
- zend_file_cache_invalidate(realpath);
- }
- #endif
- persistent_script = zend_accel_hash_find(&ZCSG(hash), realpath);
- if (persistent_script && !persistent_script->corrupted) {
- zend_file_handle file_handle;
- file_handle.type = ZEND_HANDLE_FILENAME;
- file_handle.filename = ZSTR_VAL(realpath);
- file_handle.opened_path = realpath;
- if (force ||
- !ZCG(accel_directives).validate_timestamps ||
- do_validate_timestamps(persistent_script, &file_handle) == FAILURE) {
- HANDLE_BLOCK_INTERRUPTIONS();
- SHM_UNPROTECT();
- zend_shared_alloc_lock();
- if (!persistent_script->corrupted) {
- persistent_script->corrupted = 1;
- persistent_script->timestamp = 0;
- ZSMMG(wasted_shared_memory) += persistent_script->dynamic_members.memory_consumption;
- if (ZSMMG(memory_exhausted)) {
- zend_accel_restart_reason reason =
- zend_accel_hash_is_full(&ZCSG(hash)) ? ACCEL_RESTART_HASH : ACCEL_RESTART_OOM;
- zend_accel_schedule_restart_if_necessary(reason);
- }
- }
- zend_shared_alloc_unlock();
- SHM_PROTECT();
- HANDLE_UNBLOCK_INTERRUPTIONS();
- }
- }
- accelerator_shm_read_unlock();
- zend_string_release_ex(realpath, 0);
- return SUCCESS;
- }
- /* Adds another key for existing cached script */
- static void zend_accel_add_key(const char *key, unsigned int key_length, zend_accel_hash_entry *bucket)
- {
- if (!zend_accel_hash_str_find(&ZCSG(hash), key, key_length)) {
- if (zend_accel_hash_is_full(&ZCSG(hash))) {
- zend_accel_error(ACCEL_LOG_DEBUG, "No more entries in hash table!");
- ZSMMG(memory_exhausted) = 1;
- zend_accel_schedule_restart_if_necessary(ACCEL_RESTART_HASH);
- } else {
- char *new_key = zend_shared_alloc(key_length + 1);
- if (new_key) {
- memcpy(new_key, key, key_length + 1);
- if (zend_accel_hash_update(&ZCSG(hash), new_key, key_length, 1, bucket)) {
- zend_accel_error(ACCEL_LOG_INFO, "Added key '%s'", new_key);
- }
- } else {
- zend_accel_schedule_restart_if_necessary(ACCEL_RESTART_OOM);
- }
- }
- }
- }
- static zend_always_inline zend_bool is_phar_file(zend_string *filename)
- {
- return filename && ZSTR_LEN(filename) >= sizeof(".phar") &&
- !memcmp(ZSTR_VAL(filename) + ZSTR_LEN(filename) - (sizeof(".phar")-1), ".phar", sizeof(".phar")-1) &&
- !strstr(ZSTR_VAL(filename), "://");
- }
- #ifdef HAVE_OPCACHE_FILE_CACHE
- static zend_persistent_script *store_script_in_file_cache(zend_persistent_script *new_persistent_script)
- {
- uint32_t memory_used;
- zend_shared_alloc_init_xlat_table();
- /* Calculate the required memory size */
- memory_used = zend_accel_script_persist_calc(new_persistent_script, NULL, 0, 0);
- /* Allocate memory block */
- #if defined(__AVX__) || defined(__SSE2__)
- /* Align to 64-byte boundary */
- ZCG(mem) = zend_arena_alloc(&CG(arena), memory_used + 64);
- ZCG(mem) = (void*)(((zend_uintptr_t)ZCG(mem) + 63L) & ~63L);
- #elif ZEND_MM_ALIGNMENT < 8
- /* Align to 8-byte boundary */
- ZCG(mem) = zend_arena_alloc(&CG(arena), memory_used + 8);
- ZCG(mem) = (void*)(((zend_uintptr_t)ZCG(mem) + 7L) & ~7L);
- #else
- ZCG(mem) = zend_arena_alloc(&CG(arena), memory_used);
- #endif
- /* Copy into memory block */
- new_persistent_script = zend_accel_script_persist(new_persistent_script, NULL, 0, 0);
- zend_shared_alloc_destroy_xlat_table();
- new_persistent_script->is_phar = is_phar_file(new_persistent_script->script.filename);
- /* Consistency check */
- if ((char*)new_persistent_script->mem + new_persistent_script->size != (char*)ZCG(mem)) {
- zend_accel_error(
- ((char*)new_persistent_script->mem + new_persistent_script->size < (char*)ZCG(mem)) ? ACCEL_LOG_ERROR : ACCEL_LOG_WARNING,
- "Internal error: wrong size calculation: %s start=" ZEND_ADDR_FMT ", end=" ZEND_ADDR_FMT ", real=" ZEND_ADDR_FMT "\n",
- ZSTR_VAL(new_persistent_script->script.filename),
- (size_t)new_persistent_script->mem,
- (size_t)((char *)new_persistent_script->mem + new_persistent_script->size),
- (size_t)ZCG(mem));
- }
- new_persistent_script->dynamic_members.checksum = zend_accel_script_checksum(new_persistent_script);
- zend_file_cache_script_store(new_persistent_script, 0);
- return new_persistent_script;
- }
- static zend_persistent_script *cache_script_in_file_cache(zend_persistent_script *new_persistent_script, int *from_shared_memory)
- {
- uint32_t orig_compiler_options;
- /* Check if script may be stored in shared memory */
- if (!zend_accel_script_persistable(new_persistent_script)) {
- return new_persistent_script;
- }
- orig_compiler_options = CG(compiler_options);
- CG(compiler_options) |= ZEND_COMPILE_WITH_FILE_CACHE;
- if (!zend_optimize_script(&new_persistent_script->script, ZCG(accel_directives).optimization_level, ZCG(accel_directives).opt_debug_level)) {
- CG(compiler_options) = orig_compiler_options;
- return new_persistent_script;
- }
- CG(compiler_options) = orig_compiler_options;
- *from_shared_memory = 1;
- return store_script_in_file_cache(new_persistent_script);
- }
- #endif
- static zend_persistent_script *cache_script_in_shared_memory(zend_persistent_script *new_persistent_script, const char *key, unsigned int key_length, int *from_shared_memory)
- {
- zend_accel_hash_entry *bucket;
- uint32_t memory_used;
- uint32_t orig_compiler_options;
- /* Check if script may be stored in shared memory */
- if (!zend_accel_script_persistable(new_persistent_script)) {
- return new_persistent_script;
- }
- orig_compiler_options = CG(compiler_options);
- #ifdef HAVE_OPCACHE_FILE_CACHE
- if (ZCG(accel_directives).file_cache) {
- CG(compiler_options) |= ZEND_COMPILE_WITH_FILE_CACHE;
- }
- #endif
- if (!zend_optimize_script(&new_persistent_script->script, ZCG(accel_directives).optimization_level, ZCG(accel_directives).opt_debug_level)) {
- CG(compiler_options) = orig_compiler_options;
- return new_persistent_script;
- }
- CG(compiler_options) = orig_compiler_options;
- /* exclusive lock */
- zend_shared_alloc_lock();
- /* Check if we still need to put the file into the cache (may be it was
- * already stored by another process. This final check is done under
- * exclusive lock) */
- bucket = zend_accel_hash_find_entry(&ZCSG(hash), new_persistent_script->script.filename);
- if (bucket) {
- zend_persistent_script *existing_persistent_script = (zend_persistent_script *)bucket->data;
- if (!existing_persistent_script->corrupted) {
- if (key &&
- (!ZCG(accel_directives).validate_timestamps ||
- (new_persistent_script->timestamp == existing_persistent_script->timestamp))) {
- zend_accel_add_key(key, key_length, bucket);
- }
- zend_shared_alloc_unlock();
- return new_persistent_script;
- }
- }
- if (zend_accel_hash_is_full(&ZCSG(hash))) {
- zend_accel_error(ACCEL_LOG_DEBUG, "No more entries in hash table!");
- ZSMMG(memory_exhausted) = 1;
- zend_accel_schedule_restart_if_necessary(ACCEL_RESTART_HASH);
- zend_shared_alloc_unlock();
- #ifdef HAVE_OPCACHE_FILE_CACHE
- if (ZCG(accel_directives).file_cache) {
- new_persistent_script = store_script_in_file_cache(new_persistent_script);
- *from_shared_memory = 1;
- }
- #endif
- return new_persistent_script;
- }
- zend_shared_alloc_init_xlat_table();
- /* Calculate the required memory size */
- memory_used = zend_accel_script_persist_calc(new_persistent_script, key, key_length, 1);
- /* Allocate shared memory */
- #if defined(__AVX__) || defined(__SSE2__)
- /* Align to 64-byte boundary */
- ZCG(mem) = zend_shared_alloc(memory_used + 64);
- if (ZCG(mem)) {
- ZCG(mem) = (void*)(((zend_uintptr_t)ZCG(mem) + 63L) & ~63L);
- #if defined(__x86_64__)
- memset(ZCG(mem), 0, memory_used);
- #elif defined(__AVX__)
- {
- char *p = (char*)ZCG(mem);
- char *end = p + memory_used;
- __m256i ymm0 = _mm256_setzero_si256();
- while (p < end) {
- _mm256_store_si256((__m256i*)p, ymm0);
- _mm256_store_si256((__m256i*)(p+32), ymm0);
- p += 64;
- }
- }
- #else
- {
- char *p = (char*)ZCG(mem);
- char *end = p + memory_used;
- __m128i xmm0 = _mm_setzero_si128();
- while (p < end) {
- _mm_store_si128((__m128i*)p, xmm0);
- _mm_store_si128((__m128i*)(p+16), xmm0);
- _mm_store_si128((__m128i*)(p+32), xmm0);
- _mm_store_si128((__m128i*)(p+48), xmm0);
- p += 64;
- }
- }
- #endif
- }
- #else
- ZCG(mem) = zend_shared_alloc(memory_used);
- if (ZCG(mem)) {
- memset(ZCG(mem), 0, memory_used);
- }
- #endif
- if (!ZCG(mem)) {
- zend_shared_alloc_destroy_xlat_table();
- zend_accel_schedule_restart_if_necessary(ACCEL_RESTART_OOM);
- zend_shared_alloc_unlock();
- #ifdef HAVE_OPCACHE_FILE_CACHE
- if (ZCG(accel_directives).file_cache) {
- new_persistent_script = store_script_in_file_cache(new_persistent_script);
- *from_shared_memory = 1;
- }
- #endif
- return new_persistent_script;
- }
- /* Copy into shared memory */
- new_persistent_script = zend_accel_script_persist(new_persistent_script, &key, key_length, 1);
- zend_shared_alloc_destroy_xlat_table();
- new_persistent_script->is_phar = is_phar_file(new_persistent_script->script.filename);
- /* Consistency check */
- if ((char*)new_persistent_script->mem + new_persistent_script->size != (char*)ZCG(mem)) {
- zend_accel_error(
- ((char*)new_persistent_script->mem + new_persistent_script->size < (char*)ZCG(mem)) ? ACCEL_LOG_ERROR : ACCEL_LOG_WARNING,
- "Internal error: wrong size calculation: %s start=" ZEND_ADDR_FMT ", end=" ZEND_ADDR_FMT ", real=" ZEND_ADDR_FMT "\n",
- ZSTR_VAL(new_persistent_script->script.filename),
- (size_t)new_persistent_script->mem,
- (size_t)((char *)new_persistent_script->mem + new_persistent_script->size),
- (size_t)ZCG(mem));
- }
- new_persistent_script->dynamic_members.checksum = zend_accel_script_checksum(new_persistent_script);
- /* store script structure in the hash table */
- bucket = zend_accel_hash_update(&ZCSG(hash), ZSTR_VAL(new_persistent_script->script.filename), ZSTR_LEN(new_persistent_script->script.filename), 0, new_persistent_script);
- if (bucket) {
- zend_accel_error(ACCEL_LOG_INFO, "Cached script '%s'", ZSTR_VAL(new_persistent_script->script.filename));
- if (key &&
- /* key may contain non-persistent PHAR aliases (see issues #115 and #149) */
- memcmp(key, "phar://", sizeof("phar://") - 1) != 0 &&
- (ZSTR_LEN(new_persistent_script->script.filename) != key_length ||
- memcmp(ZSTR_VAL(new_persistent_script->script.filename), key, key_length) != 0)) {
- /* link key to the same persistent script in hash table */
- if (zend_accel_hash_update(&ZCSG(hash), key, key_length, 1, bucket)) {
- zend_accel_error(ACCEL_LOG_INFO, "Added key '%s'", key);
- } else {
- zend_accel_error(ACCEL_LOG_DEBUG, "No more entries in hash table!");
- ZSMMG(memory_exhausted) = 1;
- zend_accel_schedule_restart_if_necessary(ACCEL_RESTART_HASH);
- }
- }
- }
- new_persistent_script->dynamic_members.memory_consumption = ZEND_ALIGNED_SIZE(new_persistent_script->size);
- zend_shared_alloc_unlock();
- #ifdef HAVE_OPCACHE_FILE_CACHE
- if (ZCG(accel_directives).file_cache) {
- SHM_PROTECT();
- zend_file_cache_script_store(new_persistent_script, 1);
- SHM_UNPROTECT();
- }
- #endif
- *from_shared_memory = 1;
- return new_persistent_script;
- }
- static const struct jit_auto_global_info
- {
- const char *name;
- size_t len;
- } jit_auto_globals_info[] = {
- { "_SERVER", sizeof("_SERVER")-1},
- { "_ENV", sizeof("_ENV")-1},
- { "_REQUEST", sizeof("_REQUEST")-1},
- { "GLOBALS", sizeof("GLOBALS")-1},
- };
- static zend_string *jit_auto_globals_str[4];
- static int zend_accel_get_auto_globals(void)
- {
- int i, ag_size = (sizeof(jit_auto_globals_info) / sizeof(jit_auto_globals_info[0]));
- int n = 1;
- int mask = 0;
- for (i = 0; i < ag_size ; i++) {
- if (zend_hash_exists(&EG(symbol_table), jit_auto_globals_str[i])) {
- mask |= n;
- }
- n += n;
- }
- return mask;
- }
- static int zend_accel_get_auto_globals_no_jit(void)
- {
- if (zend_hash_exists(&EG(symbol_table), jit_auto_globals_str[3])) {
- return 8;
- }
- return 0;
- }
- static void zend_accel_set_auto_globals(int mask)
- {
- int i, ag_size = (sizeof(jit_auto_globals_info) / sizeof(jit_auto_globals_info[0]));
- int n = 1;
- for (i = 0; i < ag_size ; i++) {
- if ((mask & n) && !(ZCG(auto_globals_mask) & n)) {
- ZCG(auto_globals_mask) |= n;
- zend_is_auto_global(jit_auto_globals_str[i]);
- }
- n += n;
- }
- }
- static void zend_accel_init_auto_globals(void)
- {
- int i, ag_size = (sizeof(jit_auto_globals_info) / sizeof(jit_auto_globals_info[0]));
- for (i = 0; i < ag_size ; i++) {
- jit_auto_globals_str[i] = zend_string_init(jit_auto_globals_info[i].name, jit_auto_globals_info[i].len, 1);
- zend_string_hash_val(jit_auto_globals_str[i]);
- jit_auto_globals_str[i] = accel_new_interned_string(jit_auto_globals_str[i]);
- }
- }
- static zend_persistent_script *opcache_compile_file(zend_file_handle *file_handle, int type, const char *key, zend_op_array **op_array_p)
- {
- zend_persistent_script *new_persistent_script;
- zend_op_array *orig_active_op_array;
- HashTable *orig_function_table, *orig_class_table;
- zval orig_user_error_handler;
- zend_op_array *op_array;
- int do_bailout = 0;
- accel_time_t timestamp = 0;
- uint32_t orig_compiler_options = 0;
- /* Try to open file */
- if (file_handle->type == ZEND_HANDLE_FILENAME) {
- if (accelerator_orig_zend_stream_open_function(file_handle->filename, file_handle) != SUCCESS) {
- *op_array_p = NULL;
- if (type == ZEND_REQUIRE) {
- zend_message_dispatcher(ZMSG_FAILED_REQUIRE_FOPEN, file_handle->filename);
- zend_bailout();
- } else {
- zend_message_dispatcher(ZMSG_FAILED_INCLUDE_FOPEN, file_handle->filename);
- }
- return NULL;
- }
- }
- /* check blacklist right after ensuring that file was opened */
- if (file_handle->opened_path && zend_accel_blacklist_is_blacklisted(&accel_blacklist, ZSTR_VAL(file_handle->opened_path), ZSTR_LEN(file_handle->opened_path))) {
- SHM_UNPROTECT();
- ZCSG(blacklist_misses)++;
- SHM_PROTECT();
- *op_array_p = accelerator_orig_compile_file(file_handle, type);
- return NULL;
- }
- if (ZCG(accel_directives).validate_timestamps ||
- ZCG(accel_directives).file_update_protection ||
- ZCG(accel_directives).max_file_size > 0) {
- size_t size = 0;
- /* Obtain the file timestamps, *before* actually compiling them,
- * otherwise we have a race-condition.
- */
- timestamp = zend_get_file_handle_timestamp(file_handle, ZCG(accel_directives).max_file_size > 0 ? &size : NULL);
- /* If we can't obtain a timestamp (that means file is possibly socket)
- * we won't cache it
- */
- if (timestamp == 0) {
- *op_array_p = accelerator_orig_compile_file(file_handle, type);
- return NULL;
- }
- /* check if file is too new (may be it's not written completely yet) */
- if (ZCG(accel_directives).file_update_protection &&
- ((accel_time_t)(ZCG(request_time) - ZCG(accel_directives).file_update_protection) < timestamp)) {
- *op_array_p = accelerator_orig_compile_file(file_handle, type);
- return NULL;
- }
- if (ZCG(accel_directives).max_file_size > 0 && size > (size_t)ZCG(accel_directives).max_file_size) {
- SHM_UNPROTECT();
- ZCSG(blacklist_misses)++;
- SHM_PROTECT();
- *op_array_p = accelerator_orig_compile_file(file_handle, type);
- return NULL;
- }
- }
- new_persistent_script = create_persistent_script();
- /* Save the original values for the op_array, function table and class table */
- orig_active_op_array = CG(active_op_array);
- orig_function_table = CG(function_table);
- orig_class_table = CG(class_table);
- ZVAL_COPY_VALUE(&orig_user_error_handler, &EG(user_error_handler));
- /* Override them with ours */
- CG(function_table) = &ZCG(function_table);
- EG(class_table) = CG(class_table) = &new_persistent_script->script.class_table;
- ZVAL_UNDEF(&EG(user_error_handler));
- zend_try {
- orig_compiler_options = CG(compiler_options);
- CG(compiler_options) |= ZEND_COMPILE_HANDLE_OP_ARRAY;
- CG(compiler_options) |= ZEND_COMPILE_IGNORE_INTERNAL_CLASSES;
- CG(compiler_options) |= ZEND_COMPILE_DELAYED_BINDING;
- CG(compiler_options) |= ZEND_COMPILE_NO_CONSTANT_SUBSTITUTION;
- #ifdef HAVE_OPCACHE_FILE_CACHE
- if (ZCG(accel_directives).file_cache) {
- CG(compiler_options) |= ZEND_COMPILE_WITH_FILE_CACHE;
- }
- #endif
- op_array = *op_array_p = accelerator_orig_compile_file(file_handle, type);
- CG(compiler_options) = orig_compiler_options;
- } zend_catch {
- op_array = NULL;
- do_bailout = 1;
- CG(compiler_options) = orig_compiler_options;
- } zend_end_try();
- /* Restore originals */
- CG(active_op_array) = orig_active_op_array;
- CG(function_table) = orig_function_table;
- EG(class_table) = CG(class_table) = orig_class_table;
- EG(user_error_handler) = orig_user_error_handler;
- if (!op_array) {
- /* compilation failed */
- free_persistent_script(new_persistent_script, 1);
- zend_accel_free_user_functions(&ZCG(function_table));
- if (do_bailout) {
- zend_bailout();
- }
- return NULL;
- }
- /* Build the persistent_script structure.
- Here we aren't sure we would store it, but we will need it
- further anyway.
- */
- zend_accel_move_user_functions(&ZCG(function_table), &new_persistent_script->script.function_table);
- new_persistent_script->script.first_early_binding_opline =
- (op_array->fn_flags & ZEND_ACC_EARLY_BINDING) ?
- zend_build_delayed_early_binding_list(op_array) :
- (uint32_t)-1;
- new_persistent_script->script.main_op_array = *op_array;
- efree(op_array); /* we have valid persistent_script, so it's safe to free op_array */
- /* Fill in the ping_auto_globals_mask for the new script. If jit for auto globals is enabled we
- will have to ping the used auto global variables before execution */
- if (PG(auto_globals_jit)) {
- new_persistent_script->ping_auto_globals_mask = zend_accel_get_auto_globals();
- } else {
- new_persistent_script->ping_auto_globals_mask = zend_accel_get_auto_globals_no_jit();
- }
- if (ZCG(accel_directives).validate_timestamps) {
- /* Obtain the file timestamps, *before* actually compiling them,
- * otherwise we have a race-condition.
- */
- new_persistent_script->timestamp = timestamp;
- new_persistent_script->dynamic_members.revalidate = ZCG(request_time) + ZCG(accel_directives).revalidate_freq;
- }
- if (file_handle->opened_path) {
- new_persistent_script->script.filename = zend_string_copy(file_handle->opened_path);
- } else {
- new_persistent_script->script.filename = zend_string_init(file_handle->filename, strlen(file_handle->filename), 0);
- }
- zend_string_hash_val(new_persistent_script->script.filename);
- /* Now persistent_script structure is ready in process memory */
- return new_persistent_script;
- }
- #ifdef HAVE_OPCACHE_FILE_CACHE
- zend_op_array *file_cache_compile_file(zend_file_handle *file_handle, int type)
- {
- zend_persistent_script *persistent_script;
- zend_op_array *op_array = NULL;
- int from_memory; /* if the script we've got is stored in SHM */
- if (is_stream_path(file_handle->filename) &&
- !is_cacheable_stream_path(file_handle->filename)) {
- return accelerator_orig_compile_file(file_handle, type);
- }
- if (!file_handle->opened_path) {
- if (file_handle->type == ZEND_HANDLE_FILENAME &&
- accelerator_orig_zend_stream_open_function(file_handle->filename, file_handle) == FAILURE) {
- if (type == ZEND_REQUIRE) {
- zend_message_dispatcher(ZMSG_FAILED_REQUIRE_FOPEN, file_handle->filename);
- zend_bailout();
- } else {
- zend_message_dispatcher(ZMSG_FAILED_INCLUDE_FOPEN, file_handle->filename);
- }
- return NULL;
- }
- }
- HANDLE_BLOCK_INTERRUPTIONS();
- SHM_UNPROTECT();
- persistent_script = zend_file_cache_script_load(file_handle);
- SHM_PROTECT();
- HANDLE_UNBLOCK_INTERRUPTIONS();
- if (persistent_script) {
- /* see bug #15471 (old BTS) */
- if (persistent_script->script.filename) {
- if (!EG(current_execute_data) || !EG(current_execute_data)->opline ||
- !EG(current_execute_data)->func ||
- !ZEND_USER_CODE(EG(current_execute_data)->func->common.type) ||
- EG(current_execute_data)->opline->opcode != ZEND_INCLUDE_OR_EVAL ||
- (EG(current_execute_data)->opline->extended_value != ZEND_INCLUDE_ONCE &&
- EG(current_execute_data)->opline->extended_value != ZEND_REQUIRE_ONCE)) {
- if (zend_hash_add_empty_element(&EG(included_files), persistent_script->script.filename) != NULL) {
- /* ext/phar has to load phar's metadata into memory */
- if (persistent_script->is_phar) {
- php_stream_statbuf ssb;
- char *fname = emalloc(sizeof("phar://") + ZSTR_LEN(persistent_script->script.filename));
- memcpy(fname, "phar://", sizeof("phar://") - 1);
- memcpy(fname + sizeof("phar://") - 1, ZSTR_VAL(persistent_script->script.filename), ZSTR_LEN(persistent_script->script.filename) + 1);
- php_stream_stat_path(fname, &ssb);
- efree(fname);
- }
- }
- }
- }
- zend_file_handle_dtor(file_handle);
- if (persistent_script->ping_auto_globals_mask) {
- zend_accel_set_auto_globals(persistent_script->ping_auto_globals_mask);
- }
- return zend_accel_load_script(persistent_script, 1);
- }
- persistent_script = opcache_compile_file(file_handle, type, NULL, &op_array);
- if (persistent_script) {
- from_memory = 0;
- persistent_script = cache_script_in_file_cache(persistent_script, &from_memory);
- return zend_accel_load_script(persistent_script, from_memory);
- }
- return op_array;
- }
- #endif
- int check_persistent_script_access(zend_persistent_script *persistent_script)
- {
- char *phar_path, *ptr;
- int ret;
- if ((ZSTR_LEN(persistent_script->script.filename)<sizeof("phar://.phar")) ||
- memcmp(ZSTR_VAL(persistent_script->script.filename), "phar://", sizeof("phar://")-1)) {
- return access(ZSTR_VAL(persistent_script->script.filename), R_OK) != 0;
- } else {
- /* we got a cached file from .phar, so we have to strip prefix and path inside .phar to check access() */
- phar_path = estrdup(ZSTR_VAL(persistent_script->script.filename)+sizeof("phar://")-1);
- if ((ptr = strstr(phar_path, ".phar/")) != NULL)
- {
- *(ptr+sizeof(".phar/")-2) = 0; /* strip path inside .phar file */
- }
- ret = access(phar_path, R_OK) != 0;
- efree(phar_path);
- return ret;
- }
- }
- /* zend_compile() replacement */
- zend_op_array *persistent_compile_file(zend_file_handle *file_handle, int type)
- {
- zend_persistent_script *persistent_script = NULL;
- char *key = NULL;
- int key_length;
- int from_shared_memory; /* if the script we've got is stored in SHM */
- if (!file_handle->filename || !ZCG(accelerator_enabled)) {
- /* The Accelerator is disabled, act as if without the Accelerator */
- ZCG(cache_opline) = NULL;
- ZCG(cache_persistent_script) = NULL;
- #ifdef HAVE_OPCACHE_FILE_CACHE
- if (file_handle->filename
- && ZCG(accel_directives).file_cache
- && ZCG(enabled) && accel_startup_ok) {
- return file_cache_compile_file(file_handle, type);
- }
- #endif
- return accelerator_orig_compile_file(file_handle, type);
- #ifdef HAVE_OPCACHE_FILE_CACHE
- } else if (file_cache_only) {
- ZCG(cache_opline) = NULL;
- ZCG(cache_persistent_script) = NULL;
- return file_cache_compile_file(file_handle, type);
- #endif
- } else if (!ZCG(accelerator_enabled) ||
- (ZCSG(restart_in_progress) && accel_restart_is_active())) {
- #ifdef HAVE_OPCACHE_FILE_CACHE
- if (ZCG(accel_directives).file_cache) {
- return file_cache_compile_file(file_handle, type);
- }
- #endif
- ZCG(cache_opline) = NULL;
- ZCG(cache_persistent_script) = NULL;
- return accelerator_orig_compile_file(file_handle, type);
- }
- /* In case this callback is called from include_once, require_once or it's
- * a main FastCGI request, the key must be already calculated, and cached
- * persistent script already found */
- if (ZCG(cache_persistent_script) &&
- ((!EG(current_execute_data) &&
- file_handle->filename == SG(request_info).path_translated &&
- ZCG(cache_opline) == NULL) ||
- (EG(current_execute_data) &&
- EG(current_execute_data)->func &&
- ZEND_USER_CODE(EG(current_execute_data)->func->common.type) &&
- ZCG(cache_opline) == EG(current_execute_data)->opline))) {
- persistent_script = ZCG(cache_persistent_script);
- if (ZCG(key_len)) {
- key = ZCG(key);
- key_length = ZCG(key_len);
- }
- } else {
- if (!ZCG(accel_directives).revalidate_path) {
- /* try to find cached script by key */
- key = accel_make_persistent_key(file_handle->filename, strlen(file_handle->filename), &key_length);
- if (!key) {
- ZCG(cache_opline) = NULL;
- ZCG(cache_persistent_script) = NULL;
- return accelerator_orig_compile_file(file_handle, type);
- }
- persistent_script = zend_accel_hash_str_find(&ZCSG(hash), key, key_length);
- } else if (UNEXPECTED(is_stream_path(file_handle->filename) && !is_cacheable_stream_path(file_handle->filename))) {
- ZCG(cache_opline) = NULL;
- ZCG(cache_persistent_script) = NULL;
- return accelerator_orig_compile_file(file_handle, type);
- }
- if (!persistent_script) {
- /* try to find cached script by full real path */
- zend_accel_hash_entry *bucket;
- /* open file to resolve the path */
- if (file_handle->type == ZEND_HANDLE_FILENAME &&
- accelerator_orig_zend_stream_open_function(file_handle->filename, file_handle) == FAILURE) {
- if (type == ZEND_REQUIRE) {
- zend_message_dispatcher(ZMSG_FAILED_REQUIRE_FOPEN, file_handle->filename);
- zend_bailout();
- } else {
- zend_message_dispatcher(ZMSG_FAILED_INCLUDE_FOPEN, file_handle->filename);
- }
- return NULL;
- }
- if (file_handle->opened_path) {
- bucket = zend_accel_hash_find_entry(&ZCSG(hash), file_handle->opened_path);
- if (bucket) {
- persistent_script = (zend_persistent_script *)bucket->data;
- if (key && !persistent_script->corrupted) {
- HANDLE_BLOCK_INTERRUPTIONS();
- SHM_UNPROTECT();
- zend_shared_alloc_lock();
- zend_accel_add_key(key, key_length, bucket);
- zend_shared_alloc_unlock();
- SHM_PROTECT();
- HANDLE_UNBLOCK_INTERRUPTIONS();
- }
- }
- }
- }
- }
- /* clear cache */
- ZCG(cache_opline) = NULL;
- ZCG(cache_persistent_script) = NULL;
- if (persistent_script && persistent_script->corrupted) {
- persistent_script = NULL;
- }
- /* Make sure we only increase the currently running processes semaphore
- * once each execution (this function can be called more than once on
- * each execution)
- */
- if (!ZCG(counted)) {
- if (accel_activate_add() == FAILURE) {
- #ifdef HAVE_OPCACHE_FILE_CACHE
- if (ZCG(accel_directives).file_cache) {
- return file_cache_compile_file(file_handle, type);
- }
- #endif
- return accelerator_orig_compile_file(file_handle, type);
- }
- ZCG(counted) = 1;
- }
- /* Revalidate acessibility of cached file */
- if (EXPECTED(persistent_script != NULL) &&
- UNEXPECTED(ZCG(accel_directives).validate_permission) &&
- file_handle->type == ZEND_HANDLE_FILENAME &&
- UNEXPECTED(check_persistent_script_access(persistent_script))) {
- if (type == ZEND_REQUIRE) {
- zend_message_dispatcher(ZMSG_FAILED_REQUIRE_FOPEN, file_handle->filename);
- zend_bailout();
- } else {
- zend_message_dispatcher(ZMSG_FAILED_INCLUDE_FOPEN, file_handle->filename);
- }
- return NULL;
- }
- HANDLE_BLOCK_INTERRUPTIONS();
- SHM_UNPROTECT();
- /* If script is found then validate_timestamps if option is enabled */
- if (persistent_script && ZCG(accel_directives).validate_timestamps) {
- if (validate_timestamp_and_record(persistent_script, file_handle) == FAILURE) {
- zend_shared_alloc_lock();
- if (!persistent_script->corrupted) {
- persistent_script->corrupted = 1;
- persistent_script->timestamp = 0;
- ZSMMG(wasted_shared_memory) += persistent_script->dynamic_members.memory_consumption;
- if (ZSMMG(memory_exhausted)) {
- zend_accel_restart_reason reason =
- zend_accel_hash_is_full(&ZCSG(hash)) ? ACCEL_RESTART_HASH : ACCEL_RESTART_OOM;
- zend_accel_schedule_restart_if_necessary(reason);
- }
- }
- zend_shared_alloc_unlock();
- persistent_script = NULL;
- }
- }
- /* if turned on - check the compiled script ADLER32 checksum */
- if (persistent_script && ZCG(accel_directives).consistency_checks
- && persistent_script->dynamic_members.hits % ZCG(accel_directives).consistency_checks == 0) {
- unsigned int checksum = zend_accel_script_checksum(persistent_script);
- if (checksum != persistent_script->dynamic_members.checksum ) {
- /* The checksum is wrong */
- zend_accel_error(ACCEL_LOG_INFO, "Checksum failed for '%s': expected=0x%08x, found=0x%08x",
- ZSTR_VAL(persistent_script->script.filename), persistent_script->dynamic_members.checksum, checksum);
- zend_shared_alloc_lock();
- if (!persistent_script->corrupted) {
- persistent_script->corrupted = 1;
- persistent_script->timestamp = 0;
- ZSMMG(wasted_shared_memory) += persistent_script->dynamic_members.memory_consumption;
- if (ZSMMG(memory_exhausted)) {
- zend_accel_restart_reason reason =
- zend_accel_hash_is_full(&ZCSG(hash)) ? ACCEL_RESTART_HASH : ACCEL_RESTART_OOM;
- zend_accel_schedule_restart_if_necessary(reason);
- }
- }
- zend_shared_alloc_unlock();
- persistent_script = NULL;
- }
- }
- #ifdef HAVE_OPCACHE_FILE_CACHE
- /* Check the second level cache */
- if (!persistent_script && ZCG(accel_directives).file_cache) {
- persistent_script = zend_file_cache_script_load(file_handle);
- }
- #endif
- /* If script was not found or invalidated by validate_timestamps */
- if (!persistent_script) {
- uint32_t old_const_num = zend_hash_next_free_element(EG(zend_constants));
- zend_op_array *op_array;
- /* Cache miss.. */
- ZCSG(misses)++;
- /* No memory left. Behave like without the Accelerator */
- if (ZSMMG(memory_exhausted) || ZCSG(restart_pending)) {
- SHM_PROTECT();
- HANDLE_UNBLOCK_INTERRUPTIONS();
- #ifdef HAVE_OPCACHE_FILE_CACHE
- if (ZCG(accel_directives).file_cache) {
- return file_cache_compile_file(file_handle, type);
- }
- #endif
- return accelerator_orig_compile_file(file_handle, type);
- }
- SHM_PROTECT();
- HANDLE_UNBLOCK_INTERRUPTIONS();
- persistent_script = opcache_compile_file(file_handle, type, key, &op_array);
- HANDLE_BLOCK_INTERRUPTIONS();
- SHM_UNPROTECT();
- /* Try and cache the script and assume that it is returned from_shared_memory.
- * If it isn't compile_and_cache_file() changes the flag to 0
- */
- from_shared_memory = 0;
- if (persistent_script) {
- persistent_script = cache_script_in_shared_memory(persistent_script, key, key ? key_length : 0, &from_shared_memory);
- }
- /* Caching is disabled, returning op_array;
- * or something went wrong during compilation, returning NULL
- */
- if (!persistent_script) {
- SHM_PROTECT();
- HANDLE_UNBLOCK_INTERRUPTIONS();
- return op_array;
- }
- if (from_shared_memory) {
- /* Delete immutable arrays moved into SHM */
- uint32_t new_const_num = zend_hash_next_free_element(EG(zend_constants));
- while (new_const_num > old_const_num) {
- new_const_num--;
- zend_hash_index_del(EG(zend_constants), new_const_num);
- }
- }
- } else {
- #if !ZEND_WIN32
- ZCSG(hits)++; /* TBFixed: may lose one hit */
- persistent_script->dynamic_members.hits++; /* see above */
- #else
- #ifdef _M_X64
- InterlockedIncrement64(&ZCSG(hits));
- #else
- InterlockedIncrement(&ZCSG(hits));
- #endif
- InterlockedIncrement64(&persistent_script->dynamic_members.hits);
- #endif
- /* see bug #15471 (old BTS) */
- if (persistent_script->script.filename) {
- if (!EG(current_execute_data) || !EG(current_execute_data)->opline ||
- !EG(current_execute_data)->func ||
- !ZEND_USER_CODE(EG(current_execute_data)->func->common.type) ||
- EG(current_execute_data)->opline->opcode != ZEND_INCLUDE_OR_EVAL ||
- (EG(current_execute_data)->opline->extended_value != ZEND_INCLUDE_ONCE &&
- EG(current_execute_data)->opline->extended_value != ZEND_REQUIRE_ONCE)) {
- if (zend_hash_add_empty_element(&EG(included_files), persistent_script->script.filename) != NULL) {
- /* ext/phar has to load phar's metadata into memory */
- if (persistent_script->is_phar) {
- php_stream_statbuf ssb;
- char *fname = emalloc(sizeof("phar://") + ZSTR_LEN(persistent_script->script.filename));
- memcpy(fname, "phar://", sizeof("phar://") - 1);
- memcpy(fname + sizeof("phar://") - 1, ZSTR_VAL(persistent_script->script.filename), ZSTR_LEN(persistent_script->script.filename) + 1);
- php_stream_stat_path(fname, &ssb);
- efree(fname);
- }
- }
- }
- }
- zend_file_handle_dtor(file_handle);
- from_shared_memory = 1;
- }
- persistent_script->dynamic_members.last_used = ZCG(request_time);
- SHM_PROTECT();
- HANDLE_UNBLOCK_INTERRUPTIONS();
- /* Fetch jit auto globals used in the script before execution */
- if (persistent_script->ping_auto_globals_mask) {
- zend_accel_set_auto_globals(persistent_script->ping_auto_globals_mask);
- }
- return zend_accel_load_script(persistent_script, from_shared_memory);
- }
- /* zend_stream_open_function() replacement for PHP 5.3 and above */
- static int persistent_stream_open_function(const char *filename, zend_file_handle *handle)
- {
- if (ZCG(cache_persistent_script)) {
- /* check if callback is called from include_once or it's a main request */
- if ((!EG(current_execute_data) &&
- filename == SG(request_info).path_translated &&
- ZCG(cache_opline) == NULL) ||
- (EG(current_execute_data) &&
- EG(current_execute_data)->func &&
- ZEND_USER_CODE(EG(current_execute_data)->func->common.type) &&
- ZCG(cache_opline) == EG(current_execute_data)->opline)) {
- /* we are in include_once or FastCGI request */
- handle->filename = (char*)filename;
- handle->free_filename = 0;
- handle->opened_path = zend_string_copy(ZCG(cache_persistent_script)->script.filename);
- handle->type = ZEND_HANDLE_FILENAME;
- return SUCCESS;
- }
- ZCG(cache_opline) = NULL;
- ZCG(cache_persistent_script) = NULL;
- }
- return accelerator_orig_zend_stream_open_function(filename, handle);
- }
- /* zend_resolve_path() replacement for PHP 5.3 and above */
- static zend_string* persistent_zend_resolve_path(const char *filename, size_t filename_len)
- {
- if (
- #ifdef HAVE_OPCACHE_FILE_CACHE
- !file_cache_only &&
- #endif
- ZCG(accelerator_enabled)) {
- /* check if callback is called from include_once or it's a main request */
- if ((!EG(current_execute_data) &&
- filename == SG(request_info).path_translated) ||
- (EG(current_execute_data) &&
- EG(current_execute_data)->func &&
- ZEND_USER_CODE(EG(current_execute_data)->func->common.type) &&
- EG(current_execute_data)->opline->opcode == ZEND_INCLUDE_OR_EVAL &&
- (EG(current_execute_data)->opline->extended_value == ZEND_INCLUDE_ONCE ||
- EG(current_execute_data)->opline->extended_value == ZEND_REQUIRE_ONCE))) {
- /* we are in include_once or FastCGI request */
- zend_string *resolved_path;
- int key_length;
- char *key = NULL;
- if (!ZCG(accel_directives).revalidate_path) {
- /* lookup by "not-real" path */
- key = accel_make_persistent_key(filename, filename_len, &key_length);
- if (key) {
- zend_accel_hash_entry *bucket = zend_accel_hash_str_find_entry(&ZCSG(hash), key, key_length);
- if (bucket != NULL) {
- zend_persistent_script *persistent_script = (zend_persistent_script *)bucket->data;
- if (!persistent_script->corrupted) {
- ZCG(cache_opline) = EG(current_execute_data) ? EG(current_execute_data)->opline : NULL;
- ZCG(cache_persistent_script) = persistent_script;
- return zend_string_copy(persistent_script->script.filename);
- }
- }
- } else {
- ZCG(cache_opline) = NULL;
- ZCG(cache_persistent_script) = NULL;
- return accelerator_orig_zend_resolve_path(filename, filename_len);
- }
- }
- /* find the full real path */
- resolved_path = accelerator_orig_zend_resolve_path(filename, filename_len);
- if (resolved_path) {
- /* lookup by real path */
- zend_accel_hash_entry *bucket = zend_accel_hash_find_entry(&ZCSG(hash), resolved_path);
- if (bucket) {
- zend_persistent_script *persistent_script = (zend_persistent_script *)bucket->data;
- if (!persistent_script->corrupted) {
- if (key) {
- /* add another "key" for the same bucket */
- HANDLE_BLOCK_INTERRUPTIONS();
- SHM_UNPROTECT();
- zend_shared_alloc_lock();
- zend_accel_add_key(key, key_length, bucket);
- zend_shared_alloc_unlock();
- SHM_PROTECT();
- HANDLE_UNBLOCK_INTERRUPTIONS();
- } else {
- ZCG(key_len) = 0;
- }
- ZCG(cache_opline) = EG(current_execute_data) ? EG(current_execute_data)->opline : NULL;
- ZCG(cache_persistent_script) = persistent_script;
- return resolved_path;
- }
- }
- }
- ZCG(cache_opline) = NULL;
- ZCG(cache_persistent_script) = NULL;
- return resolved_path;
- }
- }
- ZCG(cache_opline) = NULL;
- ZCG(cache_persistent_script) = NULL;
- return accelerator_orig_zend_resolve_path(filename, filename_len);
- }
- static void zend_reset_cache_vars(void)
- {
- ZSMMG(memory_exhausted) = 0;
- ZCSG(hits) = 0;
- ZCSG(misses) = 0;
- ZCSG(blacklist_misses) = 0;
- ZSMMG(wasted_shared_memory) = 0;
- ZCSG(restart_pending) = 0;
- ZCSG(force_restart_time) = 0;
- }
- static void accel_reset_pcre_cache(void)
- {
- Bucket *p;
- ZEND_HASH_FOREACH_BUCKET(&PCRE_G(pcre_cache), p) {
- /* Remove PCRE cache entries with inconsistent keys */
- if (zend_accel_in_shm(p->key)) {
- p->key = NULL;
- zend_hash_del_bucket(&PCRE_G(pcre_cache), p);
- }
- } ZEND_HASH_FOREACH_END();
- }
- static void accel_activate(void)
- {
- if (!ZCG(enabled) || !accel_startup_ok) {
- ZCG(accelerator_enabled) = 0;
- return;
- }
- if (!ZCG(function_table).nTableSize) {
- zend_hash_init(&ZCG(function_table), zend_hash_num_elements(CG(function_table)), NULL, ZEND_FUNCTION_DTOR, 1);
- zend_accel_copy_internal_functions();
- }
- /* PHP-5.4 and above return "double", but we use 1 sec precision */
- ZCG(auto_globals_mask) = 0;
- ZCG(request_time) = (time_t)sapi_get_request_time();
- ZCG(cache_opline) = NULL;
- ZCG(cache_persistent_script) = NULL;
- ZCG(include_path_key_len) = 0;
- ZCG(include_path_check) = 1;
- /* check if ZCG(function_table) wasn't somehow polluted on the way */
- if (ZCG(internal_functions_count) != (zend_long)zend_hash_num_elements(&ZCG(function_table))) {
- 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)));
- }
- ZCG(cwd) = NULL;
- ZCG(cwd_key_len) = 0;
- ZCG(cwd_check) = 1;
- #ifdef HAVE_OPCACHE_FILE_CACHE
- if (file_cache_only) {
- ZCG(accelerator_enabled) = 0;
- return;
- }
- #endif
- #ifndef ZEND_WIN32
- if (ZCG(accel_directives).validate_root) {
- struct stat buf;
- if (stat("/", &buf) != 0) {
- ZCG(root_hash) = 0;
- } else {
- ZCG(root_hash) = buf.st_ino;
- if (sizeof(buf.st_ino) > sizeof(ZCG(root_hash))) {
- if (ZCG(root_hash) != buf.st_ino) {
- zend_string *key = zend_string_init("opcache.enable", sizeof("opcache.enable")-1, 0);
- zend_alter_ini_entry_chars(key, "0", 1, ZEND_INI_SYSTEM, ZEND_INI_STAGE_RUNTIME);
- zend_string_release_ex(key, 0);
- zend_accel_error(ACCEL_LOG_WARNING, "Can't cache files in chroot() directory with too big inode");
- return;
- }
- }
- }
- } else {
- ZCG(root_hash) = 0;
- }
- #endif
- HANDLE_BLOCK_INTERRUPTIONS();
- SHM_UNPROTECT();
- if (ZCG(counted)) {
- #ifdef ZTS
- zend_accel_error(ACCEL_LOG_WARNING, "Stuck count for thread id %lu", (unsigned long) tsrm_thread_id());
- #else
- zend_accel_error(ACCEL_LOG_WARNING, "Stuck count for pid %d", getpid());
- #endif
- accel_unlock_all();
- ZCG(counted) = 0;
- }
- if (ZCSG(restart_pending)) {
- zend_shared_alloc_lock();
- if (ZCSG(restart_pending) != 0) { /* check again, to ensure that the cache wasn't already cleaned by another process */
- if (accel_is_inactive() == SUCCESS) {
- zend_accel_error(ACCEL_LOG_DEBUG, "Restarting!");
- ZCSG(restart_pending) = 0;
- switch ZCSG(restart_reason) {
- case ACCEL_RESTART_OOM:
- ZCSG(oom_restarts)++;
- break;
- case ACCEL_RESTART_HASH:
- ZCSG(hash_restarts)++;
- break;
- case ACCEL_RESTART_USER:
- ZCSG(manual_restarts)++;
- break;
- }
- accel_restart_enter();
- zend_reset_cache_vars();
- zend_accel_hash_clean(&ZCSG(hash));
- if (ZCG(accel_directives).interned_strings_buffer) {
- accel_interned_strings_restore_state();
- }
- zend_shared_alloc_restore_state();
- ZCSG(accelerator_enabled) = ZCSG(cache_status_before_restart);
- if (ZCSG(last_restart_time) < ZCG(request_time)) {
- ZCSG(last_restart_time) = ZCG(request_time);
- } else {
- ZCSG(last_restart_time)++;
- }
- accel_restart_leave();
- }
- }
- zend_shared_alloc_unlock();
- }
- ZCG(accelerator_enabled) = ZCSG(accelerator_enabled);
- SHM_PROTECT();
- HANDLE_UNBLOCK_INTERRUPTIONS();
- if (ZCG(accelerator_enabled) && ZCSG(last_restart_time) != ZCG(last_restart_time)) {
- /* SHM was reinitialized. */
- ZCG(last_restart_time) = ZCSG(last_restart_time);
- /* Reset in-process realpath cache */
- realpath_cache_clean();
- accel_reset_pcre_cache();
- ZCG(pcre_reseted) = 0;
- } else if (!ZCG(accelerator_enabled) && !ZCG(pcre_reseted)) {
- accel_reset_pcre_cache();
- ZCG(pcre_reseted) = 1;
- }
- }
- int accel_post_deactivate(void)
- {
- if (!ZCG(enabled) || !accel_startup_ok) {
- return SUCCESS;
- }
- zend_shared_alloc_safe_unlock(); /* be sure we didn't leave cache locked */
- accel_unlock_all();
- ZCG(counted) = 0;
- return SUCCESS;
- }
- static void accel_deactivate(void)
- {
- /* ensure that we restore function_table and class_table
- * In general, they're restored by persistent_compile_file(), but in case
- * the script is aborted abnormally, they may become messed up.
- */
- if (ZCG(cwd)) {
- zend_string_release_ex(ZCG(cwd), 0);
- ZCG(cwd) = NULL;
- }
- }
- static int accelerator_remove_cb(zend_extension *element1, zend_extension *element2)
- {
- (void)element2; /* keep the compiler happy */
- if (!strcmp(element1->name, ACCELERATOR_PRODUCT_NAME )) {
- element1->startup = NULL;
- #if 0
- /* We have to call shutdown callback it to free TS resources */
- element1->shutdown = NULL;
- #endif
- element1->activate = NULL;
- element1->deactivate = NULL;
- element1->op_array_handler = NULL;
- #ifdef __DEBUG_MESSAGES__
- fprintf(stderr, ACCELERATOR_PRODUCT_NAME " is disabled: %s\n", (zps_failure_reason ? zps_failure_reason : "unknown error"));
- fflush(stderr);
- #endif
- }
- return 0;
- }
- static void zps_startup_failure(char *reason, char *api_reason, int (*cb)(zend_extension *, zend_extension *))
- {
- accel_startup_ok = 0;
- zps_failure_reason = reason;
- zps_api_failure_reason = api_reason?api_reason:reason;
- zend_llist_del_element(&zend_extensions, NULL, (int (*)(void *, void *))cb);
- }
- static inline int accel_find_sapi(void)
- {
- static const char *supported_sapis[] = {
- "apache",
- "fastcgi",
- "cli-server",
- "cgi-fcgi",
- "fpm-fcgi",
- "fpmi-fcgi",
- "apache2handler",
- "litespeed",
- "uwsgi",
- NULL
- };
- const char **sapi_name;
- if (sapi_module.name) {
- for (sapi_name = supported_sapis; *sapi_name; sapi_name++) {
- if (strcmp(sapi_module.name, *sapi_name) == 0) {
- return SUCCESS;
- }
- }
- if (ZCG(accel_directives).enable_cli && (
- strcmp(sapi_module.name, "cli") == 0
- || strcmp(sapi_module.name, "phpdbg") == 0)) {
- return SUCCESS;
- }
- }
- return FAILURE;
- }
- static int zend_accel_init_shm(void)
- {
- int i;
- zend_shared_alloc_lock();
- if (ZCG(accel_directives).interned_strings_buffer) {
- accel_shared_globals = zend_shared_alloc((ZCG(accel_directives).interned_strings_buffer * 1024 * 1024));
- } else {
- accel_shared_globals = zend_shared_alloc(sizeof(zend_accel_shared_globals));
- }
- if (!accel_shared_globals) {
- zend_accel_error(ACCEL_LOG_FATAL, "Insufficient shared memory!");
- zend_shared_alloc_unlock();
- return FAILURE;
- }
- memset(accel_shared_globals, 0, sizeof(zend_accel_shared_globals));
- ZSMMG(app_shared_globals) = accel_shared_globals;
- zend_accel_hash_init(&ZCSG(hash), ZCG(accel_directives).max_accelerated_files);
- if (ZCG(accel_directives).interned_strings_buffer) {
- uint32_t hash_size;
- /* must be a power of two */
- hash_size = ZCG(accel_directives).interned_strings_buffer * (32 * 1024);
- hash_size |= (hash_size >> 1);
- hash_size |= (hash_size >> 2);
- hash_size |= (hash_size >> 4);
- hash_size |= (hash_size >> 8);
- hash_size |= (hash_size >> 16);
- ZCSG(interned_strings).nTableMask = hash_size << 2;
- ZCSG(interned_strings).nNumOfElements = 0;
- ZCSG(interned_strings).start =
- (zend_string*)((char*)&ZCSG(interned_strings) +
- sizeof(zend_string_table) +
- ((hash_size + 1) * sizeof(uint32_t))) +
- 8;
- ZCSG(interned_strings).top =
- ZCSG(interned_strings).start;
- ZCSG(interned_strings).end =
- (zend_string*)((char*)accel_shared_globals +
- ZCG(accel_directives).interned_strings_buffer * 1024 * 1024);
- ZCSG(interned_strings).saved_top = NULL;
- memset((char*)&ZCSG(interned_strings) + sizeof(zend_string_table),
- STRTAB_INVALID_POS,
- (char*)ZCSG(interned_strings).start -
- ((char*)&ZCSG(interned_strings) + sizeof(zend_string_table)));
- zend_interned_strings_set_permanent_storage_copy_handlers(accel_use_shm_interned_strings, accel_use_permanent_interned_strings);
- }
- zend_interned_strings_set_request_storage_handlers(accel_new_interned_string_for_php, accel_init_interned_string_for_php);
- zend_reset_cache_vars();
- ZCSG(oom_restarts) = 0;
- ZCSG(hash_restarts) = 0;
- ZCSG(manual_restarts) = 0;
- ZCSG(accelerator_enabled) = 1;
- ZCSG(start_time) = zend_accel_get_time();
- ZCSG(last_restart_time) = 0;
- ZCSG(restart_in_progress) = 0;
- for (i = 0; i < -HT_MIN_MASK; i++) {
- ZCSG(uninitialized_bucket)[i] = HT_INVALID_IDX;
- }
- zend_shared_alloc_unlock();
- return SUCCESS;
- }
- static void accel_globals_ctor(zend_accel_globals *accel_globals)
- {
- #if defined(COMPILE_DL_OPCACHE) && defined(ZTS)
- ZEND_TSRMLS_CACHE_UPDATE();
- #endif
- memset(accel_globals, 0, sizeof(zend_accel_globals));
- /* TODO refactor to init this just once. */
- accel_gen_system_id();
- }
- static void accel_globals_dtor(zend_accel_globals *accel_globals)
- {
- if (accel_globals->function_table.nTableSize) {
- accel_globals->function_table.pDestructor = NULL;
- zend_hash_destroy(&accel_globals->function_table);
- }
- }
- #define ZEND_BIN_ID "BIN_" ZEND_TOSTR(SIZEOF_CHAR) ZEND_TOSTR(SIZEOF_INT) ZEND_TOSTR(SIZEOF_LONG) ZEND_TOSTR(SIZEOF_SIZE_T) ZEND_TOSTR(SIZEOF_ZEND_LONG) ZEND_TOSTR(ZEND_MM_ALIGNMENT)
- static void accel_gen_system_id(void)
- {
- PHP_MD5_CTX context;
- unsigned char digest[16], c;
- char *md5str = ZCG(system_id);
- int i;
- zend_module_entry *module;
- zend_extension *extension;
- zend_llist_position pos;
- PHP_MD5Init(&context);
- PHP_MD5Update(&context, PHP_VERSION, sizeof(PHP_VERSION)-1);
- PHP_MD5Update(&context, ZEND_EXTENSION_BUILD_ID, sizeof(ZEND_EXTENSION_BUILD_ID)-1);
- PHP_MD5Update(&context, ZEND_BIN_ID, sizeof(ZEND_BIN_ID)-1);
- if (strstr(PHP_VERSION, "-dev") != 0) {
- /* Development versions may be changed from build to build */
- PHP_MD5Update(&context, __DATE__, sizeof(__DATE__)-1);
- PHP_MD5Update(&context, __TIME__, sizeof(__TIME__)-1);
- }
- /* Modules may have changed after restart which can cause dangling pointers from
- * custom opcode handlers in the second-level cache files
- */
- ZEND_HASH_FOREACH_PTR(&module_registry, module) {
- PHP_MD5Update(&context, module->name, strlen(module->name));
- if (module->version != NULL) {
- PHP_MD5Update(&context, module->version, strlen(module->version));
- }
- } ZEND_HASH_FOREACH_END();
- extension = (zend_extension *) zend_llist_get_first_ex(&zend_extensions, &pos);
- while (extension) {
- PHP_MD5Update(&context, extension->name, strlen(extension->name));
- if (extension->version != NULL) {
- PHP_MD5Update(&context, extension->version, strlen(extension->version));
- }
- extension = (zend_extension *) zend_llist_get_next_ex(&zend_extensions, &pos);
- }
- PHP_MD5Final(digest, &context);
- for (i = 0; i < 16; i++) {
- c = digest[i] >> 4;
- c = (c <= 9) ? c + '0' : c - 10 + 'a';
- md5str[i * 2] = c;
- c = digest[i] & 0x0f;
- c = (c <= 9) ? c + '0' : c - 10 + 'a';
- md5str[(i * 2) + 1] = c;
- }
- }
- #ifdef HAVE_HUGE_CODE_PAGES
- # ifndef _WIN32
- # include <sys/mman.h>
- # ifndef MAP_ANON
- # ifdef MAP_ANONYMOUS
- # define MAP_ANON MAP_ANONYMOUS
- # endif
- # endif
- # ifndef MAP_FAILED
- # define MAP_FAILED ((void*)-1)
- # endif
- # endif
- # if defined(MAP_HUGETLB) || defined(MADV_HUGEPAGE)
- static int accel_remap_huge_pages(void *start, size_t size, const char *name, size_t offset)
- {
- void *ret = MAP_FAILED;
- void *mem;
- mem = mmap(NULL, size,
- PROT_READ | PROT_WRITE,
- MAP_PRIVATE | MAP_ANONYMOUS,
- -1, 0);
- if (mem == MAP_FAILED) {
- zend_error(E_WARNING,
- ACCELERATOR_PRODUCT_NAME " huge_code_pages: mmap failed: %s (%d)",
- strerror(errno), errno);
- return -1;
- }
- memcpy(mem, start, size);
- # ifdef MAP_HUGETLB
- ret = mmap(start, size,
- PROT_READ | PROT_WRITE | PROT_EXEC,
- MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED | MAP_HUGETLB,
- -1, 0);
- # endif
- if (ret == MAP_FAILED) {
- ret = mmap(start, size,
- PROT_READ | PROT_WRITE | PROT_EXEC,
- MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED,
- -1, 0);
- /* this should never happen? */
- ZEND_ASSERT(ret != MAP_FAILED);
- # ifdef MADV_HUGEPAGE
- if (-1 == madvise(start, size, MADV_HUGEPAGE)) {
- memcpy(start, mem, size);
- mprotect(start, size, PROT_READ | PROT_EXEC);
- munmap(mem, size);
- zend_error(E_WARNING,
- ACCELERATOR_PRODUCT_NAME " huge_code_pages: madvise(HUGEPAGE) failed: %s (%d)",
- strerror(errno), errno);
- return -1;
- }
- # else
- memcpy(start, mem, size);
- mprotect(start, size, PROT_READ | PROT_EXEC);
- munmap(mem, size);
- zend_error(E_WARNING,
- ACCELERATOR_PRODUCT_NAME " huge_code_pages: mmap(HUGETLB) failed: %s (%d)",
- strerror(errno), errno);
- return -1;
- # endif
- }
- if (ret == start) {
- memcpy(start, mem, size);
- mprotect(start, size, PROT_READ | PROT_EXEC);
- }
- munmap(mem, size);
- return (ret == start) ? 0 : -1;
- }
- static void accel_move_code_to_huge_pages(void)
- {
- FILE *f;
- long unsigned int huge_page_size = 2 * 1024 * 1024;
- f = fopen("/proc/self/maps", "r");
- if (f) {
- long unsigned int start, end, offset, inode;
- char perm[5], dev[6], name[MAXPATHLEN];
- int ret;
- ret = fscanf(f, "%lx-%lx %4s %lx %5s %ld %s\n", &start, &end, perm, &offset, dev, &inode, name);
- if (ret == 7 && perm[0] == 'r' && perm[1] == '-' && perm[2] == 'x' && name[0] == '/') {
- long unsigned int seg_start = ZEND_MM_ALIGNED_SIZE_EX(start, huge_page_size);
- long unsigned int seg_end = (end & ~(huge_page_size-1L));
- if (seg_end > seg_start) {
- zend_accel_error(ACCEL_LOG_DEBUG, "remap to huge page %lx-%lx %s \n", seg_start, seg_end, name);
- accel_remap_huge_pages((void*)seg_start, seg_end - seg_start, name, offset + seg_start - start);
- }
- }
- fclose(f);
- }
- }
- # else
- static void accel_move_code_to_huge_pages(void)
- {
- zend_error(E_WARNING, ACCELERATOR_PRODUCT_NAME ": opcache.huge_code_pages has no affect as huge page is not supported");
- return;
- }
- # endif /* defined(MAP_HUGETLB) || defined(MADV_HUGEPAGE) */
- #endif /* HAVE_HUGE_CODE_PAGES */
- static int accel_startup(zend_extension *extension)
- {
- #ifdef ZTS
- 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);
- #else
- accel_globals_ctor(&accel_globals);
- #endif
- #ifdef ZEND_WIN32
- # if !defined(__has_feature) || !__has_feature(address_sanitizer)
- _setmaxstdio(2048); /* The default configuration is limited to 512 stdio files */
- # endif
- #endif
- if (start_accel_module() == FAILURE) {
- accel_startup_ok = 0;
- zend_error(E_WARNING, ACCELERATOR_PRODUCT_NAME ": module registration failed!");
- return FAILURE;
- }
- accel_gen_system_id();
- #ifdef HAVE_HUGE_CODE_PAGES
- if (ZCG(accel_directives).huge_code_pages &&
- (strcmp(sapi_module.name, "cli") == 0 ||
- strcmp(sapi_module.name, "cli-server") == 0 ||
- strcmp(sapi_module.name, "cgi-fcgi") == 0 ||
- strcmp(sapi_module.name, "fpm-fcgi") == 0)) {
- accel_move_code_to_huge_pages();
- }
- #endif
- /* no supported SAPI found - disable acceleration and stop initialization */
- if (accel_find_sapi() == FAILURE) {
- accel_startup_ok = 0;
- if (!ZCG(accel_directives).enable_cli &&
- strcmp(sapi_module.name, "cli") == 0) {
- zps_startup_failure("Opcode Caching is disabled for CLI", NULL, accelerator_remove_cb);
- } else {
- zps_startup_failure("Opcode Caching is only supported in Apache, FPM, FastCGI and LiteSpeed SAPIs", NULL, accelerator_remove_cb);
- }
- return SUCCESS;
- }
- if (ZCG(enabled) == 0) {
- return SUCCESS ;
- }
- orig_post_startup_cb = zend_post_startup_cb;
- zend_post_startup_cb = accel_post_startup;
- return SUCCESS;
- }
- static int accel_post_startup(void)
- {
- zend_function *func;
- zend_ini_entry *ini_entry;
- if (orig_post_startup_cb) {
- int (*cb)(void) = orig_post_startup_cb;
- orig_post_startup_cb = NULL;
- if (cb() != SUCCESS) {
- return FAILURE;
- }
- }
- /********************************************/
- /* End of non-SHM dependent initializations */
- /********************************************/
- #ifdef HAVE_OPCACHE_FILE_CACHE
- file_cache_only = ZCG(accel_directives).file_cache_only;
- if (!file_cache_only) {
- #else
- if (1) {
- #endif
- switch (zend_shared_alloc_startup(ZCG(accel_directives).memory_consumption)) {
- case ALLOC_SUCCESS:
- if (zend_accel_init_shm() == FAILURE) {
- accel_startup_ok = 0;
- return FAILURE;
- }
- break;
- case ALLOC_FAILURE:
- accel_startup_ok = 0;
- zend_accel_error(ACCEL_LOG_FATAL, "Failure to initialize shared memory structures - probably not enough shared memory.");
- return SUCCESS;
- case SUCCESSFULLY_REATTACHED:
- zend_shared_alloc_lock();
- accel_shared_globals = (zend_accel_shared_globals *) ZSMMG(app_shared_globals);
- if (ZCG(accel_directives).interned_strings_buffer) {
- zend_interned_strings_set_permanent_storage_copy_handlers(accel_use_shm_interned_strings, accel_use_permanent_interned_strings);
- }
- zend_interned_strings_set_request_storage_handlers(accel_new_interned_string_for_php, accel_init_interned_string_for_php);
- zend_shared_alloc_unlock();
- break;
- case FAILED_REATTACHED:
- accel_startup_ok = 0;
- zend_accel_error(ACCEL_LOG_FATAL, "Failure to initialize shared memory structures - can not reattach to exiting shared memory.");
- return SUCCESS;
- break;
- #if ENABLE_FILE_CACHE_FALLBACK
- case ALLOC_FALLBACK:
- zend_shared_alloc_lock();
- file_cache_only = 1;
- fallback_process = 1;
- zend_accel_init_auto_globals();
- zend_shared_alloc_unlock();
- goto file_cache_fallback;
- break;
- #endif
- }
- /* from this point further, shared memory is supposed to be OK */
- /* remember the last restart time in the process memory */
- ZCG(last_restart_time) = ZCSG(last_restart_time);
- /* Init auto-global strings */
- zend_accel_init_auto_globals();
- zend_shared_alloc_lock();
- zend_shared_alloc_save_state();
- zend_shared_alloc_unlock();
- SHM_PROTECT();
- #ifdef HAVE_OPCACHE_FILE_CACHE
- } else if (!ZCG(accel_directives).file_cache) {
- accel_startup_ok = 0;
- zend_accel_error(ACCEL_LOG_FATAL, "opcache.file_cache_only is set without a proper setting of opcache.file_cache");
- return SUCCESS;
- } else {
- accel_shared_globals = calloc(1, sizeof(zend_accel_shared_globals));
- /* Init auto-global strings */
- zend_accel_init_auto_globals();
- #endif
- }
- #if ENABLE_FILE_CACHE_FALLBACK
- file_cache_fallback:
- #endif
- /* Override compiler */
- accelerator_orig_compile_file = zend_compile_file;
- zend_compile_file = persistent_compile_file;
- /* Override stream opener function (to eliminate open() call caused by
- * include/require statements ) */
- accelerator_orig_zend_stream_open_function = zend_stream_open_function;
- zend_stream_open_function = persistent_stream_open_function;
- /* Override path resolver function (to eliminate stat() calls caused by
- * include_once/require_once statements */
- accelerator_orig_zend_resolve_path = zend_resolve_path;
- zend_resolve_path = persistent_zend_resolve_path;
- /* Override chdir() function */
- if ((func = zend_hash_str_find_ptr(CG(function_table), "chdir", sizeof("chdir")-1)) != NULL &&
- func->type == ZEND_INTERNAL_FUNCTION) {
- orig_chdir = func->internal_function.handler;
- func->internal_function.handler = ZEND_FN(accel_chdir);
- }
- ZCG(cwd) = NULL;
- ZCG(include_path) = NULL;
- /* Override "include_path" modifier callback */
- if ((ini_entry = zend_hash_str_find_ptr(EG(ini_directives), "include_path", sizeof("include_path")-1)) != NULL) {
- ZCG(include_path) = ini_entry->value;
- orig_include_path_on_modify = ini_entry->on_modify;
- ini_entry->on_modify = accel_include_path_on_modify;
- }
- accel_startup_ok = 1;
- /* Override file_exists(), is_file() and is_readable() */
- zend_accel_override_file_functions();
- /* Load black list */
- accel_blacklist.entries = NULL;
- if (ZCG(enabled) && accel_startup_ok &&
- ZCG(accel_directives).user_blacklist_filename &&
- *ZCG(accel_directives.user_blacklist_filename)) {
- zend_accel_blacklist_init(&accel_blacklist);
- zend_accel_blacklist_load(&accel_blacklist, ZCG(accel_directives.user_blacklist_filename));
- }
- zend_optimizer_startup();
- return SUCCESS;
- }
- static void accel_free_ts_resources()
- {
- #ifndef ZTS
- accel_globals_dtor(&accel_globals);
- #else
- ts_free_id(accel_globals_id);
- #endif
- }
- void accel_shutdown(void)
- {
- zend_ini_entry *ini_entry;
- zend_bool _file_cache_only = 0;
- zend_optimizer_shutdown();
- zend_accel_blacklist_shutdown(&accel_blacklist);
- if (!ZCG(enabled) || !accel_startup_ok) {
- accel_free_ts_resources();
- return;
- }
- #ifdef HAVE_OPCACHE_FILE_CACHE
- _file_cache_only = file_cache_only;
- #endif
- accel_reset_pcre_cache();
- accel_free_ts_resources();
- if (!_file_cache_only) {
- zend_shared_alloc_shutdown();
- }
- zend_compile_file = accelerator_orig_compile_file;
- if ((ini_entry = zend_hash_str_find_ptr(EG(ini_directives), "include_path", sizeof("include_path")-1)) != NULL) {
- ini_entry->on_modify = orig_include_path_on_modify;
- }
- }
- void zend_accel_schedule_restart(zend_accel_restart_reason reason)
- {
- const char *zend_accel_restart_reason_text[ACCEL_RESTART_USER + 1] = {
- "out of memory",
- "hash overflow",
- "user",
- };
- if (ZCSG(restart_pending)) {
- /* don't schedule twice */
- return;
- }
- zend_accel_error(ACCEL_LOG_DEBUG, "Restart Scheduled! Reason: %s",
- zend_accel_restart_reason_text[reason]);
- HANDLE_BLOCK_INTERRUPTIONS();
- SHM_UNPROTECT();
- ZCSG(restart_pending) = 1;
- ZCSG(restart_reason) = reason;
- ZCSG(cache_status_before_restart) = ZCSG(accelerator_enabled);
- ZCSG(accelerator_enabled) = 0;
- if (ZCG(accel_directives).force_restart_timeout) {
- ZCSG(force_restart_time) = zend_accel_get_time() + ZCG(accel_directives).force_restart_timeout;
- } else {
- ZCSG(force_restart_time) = 0;
- }
- SHM_PROTECT();
- HANDLE_UNBLOCK_INTERRUPTIONS();
- }
- /* this is needed because on WIN32 lock is not decreased unless ZCG(counted) is set */
- #ifdef ZEND_WIN32
- #define accel_deactivate_now() ZCG(counted) = 1; accel_deactivate_sub()
- #else
- #define accel_deactivate_now() accel_deactivate_sub()
- #endif
- /* ensures it is OK to read SHM
- if it's not OK (restart in progress) returns FAILURE
- if OK returns SUCCESS
- MUST call accelerator_shm_read_unlock after done lock operations
- */
- int accelerator_shm_read_lock(void)
- {
- if (ZCG(counted)) {
- /* counted means we are holding read lock for SHM, so that nothing bad can happen */
- return SUCCESS;
- } else {
- /* here accelerator is active but we do not hold SHM lock. This means restart was scheduled
- or is in progress now */
- if (accel_activate_add() == FAILURE) { /* acquire usage lock */
- return FAILURE;
- }
- /* Now if we weren't inside restart, restart would not begin until we remove usage lock */
- if (ZCSG(restart_in_progress)) {
- /* we already were inside restart this means it's not safe to touch shm */
- accel_deactivate_now(); /* drop usage lock */
- return FAILURE;
- }
- ZCG(counted) = 1;
- }
- return SUCCESS;
- }
- /* must be called ONLY after SUCCESSFUL accelerator_shm_read_lock */
- void accelerator_shm_read_unlock(void)
- {
- if (!ZCG(counted)) {
- /* counted is 0 - meaning we had to readlock manually, release readlock now */
- accel_deactivate_now();
- }
- }
- ZEND_EXT_API zend_extension zend_extension_entry = {
- ACCELERATOR_PRODUCT_NAME, /* name */
- PHP_VERSION, /* version */
- "Zend Technologies", /* author */
- "http://www.zend.com/", /* URL */
- "Copyright (c) 1999-2018", /* copyright */
- accel_startup, /* startup */
- NULL, /* shutdown */
- accel_activate, /* per-script activation */
- accel_deactivate, /* per-script deactivation */
- NULL, /* message handler */
- NULL, /* op_array handler */
- NULL, /* extended statement handler */
- NULL, /* extended fcall begin handler */
- NULL, /* extended fcall end handler */
- NULL, /* op_array ctor */
- NULL, /* op_array dtor */
- STANDARD_ZEND_EXTENSION_PROPERTIES
- };
|