ZendAccelerator.c 142 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595459645974598459946004601460246034604460546064607460846094610461146124613461446154616461746184619462046214622462346244625462646274628462946304631463246334634463546364637463846394640464146424643464446454646464746484649465046514652465346544655465646574658465946604661466246634664466546664667466846694670467146724673467446754676467746784679468046814682468346844685468646874688468946904691469246934694469546964697469846994700470147024703470447054706470747084709471047114712471347144715471647174718471947204721472247234724472547264727472847294730473147324733473447354736473747384739474047414742474347444745474647474748474947504751475247534754475547564757475847594760476147624763476447654766476747684769477047714772477347744775477647774778477947804781478247834784478547864787478847894790479147924793479447954796479747984799480048014802480348044805480648074808480948104811481248134814481548164817481848194820482148224823482448254826482748284829483048314832483348344835
  1. /*
  2. +----------------------------------------------------------------------+
  3. | Zend OPcache |
  4. +----------------------------------------------------------------------+
  5. | Copyright (c) The PHP Group |
  6. +----------------------------------------------------------------------+
  7. | This source file is subject to version 3.01 of the PHP license, |
  8. | that is bundled with this package in the file LICENSE, and is |
  9. | available through the world-wide-web at the following url: |
  10. | https://www.php.net/license/3_01.txt |
  11. | If you did not receive a copy of the PHP license and are unable to |
  12. | obtain it through the world-wide-web, please send a note to |
  13. | license@php.net so we can mail you a copy immediately. |
  14. +----------------------------------------------------------------------+
  15. | Authors: Andi Gutmans <andi@php.net> |
  16. | Zeev Suraski <zeev@php.net> |
  17. | Stanislav Malyshev <stas@zend.com> |
  18. | Dmitry Stogov <dmitry@php.net> |
  19. +----------------------------------------------------------------------+
  20. */
  21. #include "main/php.h"
  22. #include "main/php_globals.h"
  23. #include "zend.h"
  24. #include "zend_extensions.h"
  25. #include "zend_compile.h"
  26. #include "ZendAccelerator.h"
  27. #include "zend_persist.h"
  28. #include "zend_shared_alloc.h"
  29. #include "zend_accelerator_module.h"
  30. #include "zend_accelerator_blacklist.h"
  31. #include "zend_list.h"
  32. #include "zend_execute.h"
  33. #include "zend_vm.h"
  34. #include "zend_inheritance.h"
  35. #include "zend_exceptions.h"
  36. #include "main/php_main.h"
  37. #include "main/SAPI.h"
  38. #include "main/php_streams.h"
  39. #include "main/php_open_temporary_file.h"
  40. #include "zend_API.h"
  41. #include "zend_ini.h"
  42. #include "zend_virtual_cwd.h"
  43. #include "zend_accelerator_util_funcs.h"
  44. #include "zend_accelerator_hash.h"
  45. #include "zend_file_cache.h"
  46. #include "ext/pcre/php_pcre.h"
  47. #include "ext/standard/md5.h"
  48. #include "ext/hash/php_hash.h"
  49. #ifdef HAVE_JIT
  50. # include "jit/zend_jit.h"
  51. #endif
  52. #ifndef ZEND_WIN32
  53. #include <netdb.h>
  54. #endif
  55. #ifdef ZEND_WIN32
  56. typedef int uid_t;
  57. typedef int gid_t;
  58. #include <io.h>
  59. #include <lmcons.h>
  60. #endif
  61. #ifndef ZEND_WIN32
  62. # include <sys/time.h>
  63. #else
  64. # include <process.h>
  65. #endif
  66. #ifdef HAVE_UNISTD_H
  67. # include <unistd.h>
  68. #endif
  69. #include <fcntl.h>
  70. #include <signal.h>
  71. #include <time.h>
  72. #ifndef ZEND_WIN32
  73. # include <sys/types.h>
  74. # include <sys/wait.h>
  75. # include <sys/ipc.h>
  76. # include <pwd.h>
  77. # include <grp.h>
  78. #endif
  79. #include <sys/stat.h>
  80. #include <errno.h>
  81. #ifdef __AVX__
  82. #include <immintrin.h>
  83. #endif
  84. ZEND_EXTENSION();
  85. #ifndef ZTS
  86. zend_accel_globals accel_globals;
  87. #else
  88. int accel_globals_id;
  89. #if defined(COMPILE_DL_OPCACHE)
  90. ZEND_TSRMLS_CACHE_DEFINE()
  91. #endif
  92. #endif
  93. /* Points to the structure shared across all PHP processes */
  94. zend_accel_shared_globals *accel_shared_globals = NULL;
  95. /* true globals, no need for thread safety */
  96. #ifdef ZEND_WIN32
  97. char accel_uname_id[32];
  98. #endif
  99. bool accel_startup_ok = 0;
  100. static char *zps_failure_reason = NULL;
  101. char *zps_api_failure_reason = NULL;
  102. bool file_cache_only = 0; /* process uses file cache only */
  103. #if ENABLE_FILE_CACHE_FALLBACK
  104. bool fallback_process = 0; /* process uses file cache fallback */
  105. #endif
  106. static zend_op_array *(*accelerator_orig_compile_file)(zend_file_handle *file_handle, int type);
  107. static zend_class_entry* (*accelerator_orig_inheritance_cache_get)(zend_class_entry *ce, zend_class_entry *parent, zend_class_entry **traits_and_interfaces);
  108. static zend_class_entry* (*accelerator_orig_inheritance_cache_add)(zend_class_entry *ce, zend_class_entry *proto, zend_class_entry *parent, zend_class_entry **traits_and_interfaces, HashTable *dependencies);
  109. static zend_result (*accelerator_orig_zend_stream_open_function)(zend_file_handle *handle );
  110. static zend_string *(*accelerator_orig_zend_resolve_path)(zend_string *filename);
  111. static zif_handler orig_chdir = NULL;
  112. static ZEND_INI_MH((*orig_include_path_on_modify)) = NULL;
  113. static zend_result (*orig_post_startup_cb)(void);
  114. static zend_result accel_post_startup(void);
  115. static int accel_finish_startup(void);
  116. static void preload_shutdown(void);
  117. static void preload_activate(void);
  118. static void preload_restart(void);
  119. #ifdef ZEND_WIN32
  120. # define INCREMENT(v) InterlockedIncrement64(&ZCSG(v))
  121. # define DECREMENT(v) InterlockedDecrement64(&ZCSG(v))
  122. # define LOCKVAL(v) (ZCSG(v))
  123. #endif
  124. #ifdef ZEND_WIN32
  125. static time_t zend_accel_get_time(void)
  126. {
  127. FILETIME now;
  128. GetSystemTimeAsFileTime(&now);
  129. return (time_t) ((((((__int64)now.dwHighDateTime) << 32)|now.dwLowDateTime) - 116444736000000000L)/10000000);
  130. }
  131. #else
  132. # define zend_accel_get_time() time(NULL)
  133. #endif
  134. static inline int is_stream_path(const char *filename)
  135. {
  136. const char *p;
  137. for (p = filename;
  138. (*p >= 'a' && *p <= 'z') ||
  139. (*p >= 'A' && *p <= 'Z') ||
  140. (*p >= '0' && *p <= '9') ||
  141. *p == '+' || *p == '-' || *p == '.';
  142. p++);
  143. return ((p != filename) && (p[0] == ':') && (p[1] == '/') && (p[2] == '/'));
  144. }
  145. static inline int is_cacheable_stream_path(const char *filename)
  146. {
  147. return memcmp(filename, "file://", sizeof("file://") - 1) == 0 ||
  148. memcmp(filename, "phar://", sizeof("phar://") - 1) == 0;
  149. }
  150. /* O+ overrides PHP chdir() function and remembers the current working directory
  151. * in ZCG(cwd) and ZCG(cwd_len). Later accel_getcwd() can use stored value and
  152. * avoid getcwd() call.
  153. */
  154. static ZEND_FUNCTION(accel_chdir)
  155. {
  156. char cwd[MAXPATHLEN];
  157. orig_chdir(INTERNAL_FUNCTION_PARAM_PASSTHRU);
  158. if (VCWD_GETCWD(cwd, MAXPATHLEN)) {
  159. if (ZCG(cwd)) {
  160. zend_string_release_ex(ZCG(cwd), 0);
  161. }
  162. ZCG(cwd) = zend_string_init(cwd, strlen(cwd), 0);
  163. } else {
  164. if (ZCG(cwd)) {
  165. zend_string_release_ex(ZCG(cwd), 0);
  166. ZCG(cwd) = NULL;
  167. }
  168. }
  169. ZCG(cwd_key_len) = 0;
  170. ZCG(cwd_check) = 1;
  171. }
  172. static inline zend_string* accel_getcwd(void)
  173. {
  174. if (ZCG(cwd)) {
  175. return ZCG(cwd);
  176. } else {
  177. char cwd[MAXPATHLEN + 1];
  178. if (!VCWD_GETCWD(cwd, MAXPATHLEN)) {
  179. return NULL;
  180. }
  181. ZCG(cwd) = zend_string_init(cwd, strlen(cwd), 0);
  182. ZCG(cwd_key_len) = 0;
  183. ZCG(cwd_check) = 1;
  184. return ZCG(cwd);
  185. }
  186. }
  187. void zend_accel_schedule_restart_if_necessary(zend_accel_restart_reason reason)
  188. {
  189. if ((((double) ZSMMG(wasted_shared_memory)) / ZCG(accel_directives).memory_consumption) >= ZCG(accel_directives).max_wasted_percentage) {
  190. zend_accel_schedule_restart(reason);
  191. }
  192. }
  193. /* O+ tracks changes of "include_path" directive. It stores all the requested
  194. * values in ZCG(include_paths) shared hash table, current value in
  195. * ZCG(include_path)/ZCG(include_path_len) and one letter "path key" in
  196. * ZCG(include_path_key).
  197. */
  198. static ZEND_INI_MH(accel_include_path_on_modify)
  199. {
  200. int ret = orig_include_path_on_modify(entry, new_value, mh_arg1, mh_arg2, mh_arg3, stage);
  201. if (ret == SUCCESS) {
  202. ZCG(include_path) = new_value;
  203. ZCG(include_path_key_len) = 0;
  204. ZCG(include_path_check) = 1;
  205. }
  206. return ret;
  207. }
  208. static inline void accel_restart_enter(void)
  209. {
  210. #ifdef ZEND_WIN32
  211. INCREMENT(restart_in);
  212. #else
  213. struct flock restart_in_progress;
  214. restart_in_progress.l_type = F_WRLCK;
  215. restart_in_progress.l_whence = SEEK_SET;
  216. restart_in_progress.l_start = 2;
  217. restart_in_progress.l_len = 1;
  218. if (fcntl(lock_file, F_SETLK, &restart_in_progress) == -1) {
  219. zend_accel_error(ACCEL_LOG_DEBUG, "RestartC(+1): %s (%d)", strerror(errno), errno);
  220. }
  221. #endif
  222. ZCSG(restart_in_progress) = 1;
  223. }
  224. static inline void accel_restart_leave(void)
  225. {
  226. #ifdef ZEND_WIN32
  227. ZCSG(restart_in_progress) = 0;
  228. DECREMENT(restart_in);
  229. #else
  230. struct flock restart_finished;
  231. restart_finished.l_type = F_UNLCK;
  232. restart_finished.l_whence = SEEK_SET;
  233. restart_finished.l_start = 2;
  234. restart_finished.l_len = 1;
  235. ZCSG(restart_in_progress) = 0;
  236. if (fcntl(lock_file, F_SETLK, &restart_finished) == -1) {
  237. zend_accel_error(ACCEL_LOG_DEBUG, "RestartC(-1): %s (%d)", strerror(errno), errno);
  238. }
  239. #endif
  240. }
  241. static inline int accel_restart_is_active(void)
  242. {
  243. if (ZCSG(restart_in_progress)) {
  244. #ifndef ZEND_WIN32
  245. struct flock restart_check;
  246. restart_check.l_type = F_WRLCK;
  247. restart_check.l_whence = SEEK_SET;
  248. restart_check.l_start = 2;
  249. restart_check.l_len = 1;
  250. if (fcntl(lock_file, F_GETLK, &restart_check) == -1) {
  251. zend_accel_error(ACCEL_LOG_DEBUG, "RestartC: %s (%d)", strerror(errno), errno);
  252. return FAILURE;
  253. }
  254. if (restart_check.l_type == F_UNLCK) {
  255. ZCSG(restart_in_progress) = 0;
  256. return 0;
  257. } else {
  258. return 1;
  259. }
  260. #else
  261. return LOCKVAL(restart_in) != 0;
  262. #endif
  263. }
  264. return 0;
  265. }
  266. /* Creates a read lock for SHM access */
  267. static inline zend_result accel_activate_add(void)
  268. {
  269. #ifdef ZEND_WIN32
  270. SHM_UNPROTECT();
  271. INCREMENT(mem_usage);
  272. SHM_PROTECT();
  273. #else
  274. struct flock mem_usage_lock;
  275. mem_usage_lock.l_type = F_RDLCK;
  276. mem_usage_lock.l_whence = SEEK_SET;
  277. mem_usage_lock.l_start = 1;
  278. mem_usage_lock.l_len = 1;
  279. if (fcntl(lock_file, F_SETLK, &mem_usage_lock) == -1) {
  280. zend_accel_error(ACCEL_LOG_DEBUG, "UpdateC(+1): %s (%d)", strerror(errno), errno);
  281. return FAILURE;
  282. }
  283. #endif
  284. return SUCCESS;
  285. }
  286. /* Releases a lock for SHM access */
  287. static inline void accel_deactivate_sub(void)
  288. {
  289. #ifdef ZEND_WIN32
  290. if (ZCG(counted)) {
  291. SHM_UNPROTECT();
  292. DECREMENT(mem_usage);
  293. ZCG(counted) = 0;
  294. SHM_PROTECT();
  295. }
  296. #else
  297. struct flock mem_usage_unlock;
  298. mem_usage_unlock.l_type = F_UNLCK;
  299. mem_usage_unlock.l_whence = SEEK_SET;
  300. mem_usage_unlock.l_start = 1;
  301. mem_usage_unlock.l_len = 1;
  302. if (fcntl(lock_file, F_SETLK, &mem_usage_unlock) == -1) {
  303. zend_accel_error(ACCEL_LOG_DEBUG, "UpdateC(-1): %s (%d)", strerror(errno), errno);
  304. }
  305. #endif
  306. }
  307. static inline void accel_unlock_all(void)
  308. {
  309. #ifdef ZEND_WIN32
  310. accel_deactivate_sub();
  311. #else
  312. struct flock mem_usage_unlock_all;
  313. mem_usage_unlock_all.l_type = F_UNLCK;
  314. mem_usage_unlock_all.l_whence = SEEK_SET;
  315. mem_usage_unlock_all.l_start = 0;
  316. mem_usage_unlock_all.l_len = 0;
  317. if (fcntl(lock_file, F_SETLK, &mem_usage_unlock_all) == -1) {
  318. zend_accel_error(ACCEL_LOG_DEBUG, "UnlockAll: %s (%d)", strerror(errno), errno);
  319. }
  320. #endif
  321. }
  322. /* Interned strings support */
  323. /* O+ disables creation of interned strings by regular PHP compiler, instead,
  324. * it creates interned strings in shared memory when saves a script.
  325. * Such interned strings are shared across all PHP processes
  326. */
  327. #define STRTAB_INVALID_POS 0
  328. #define STRTAB_HASH_TO_SLOT(tab, h) \
  329. ((uint32_t*)((char*)(tab) + sizeof(*(tab)) + ((h) & (tab)->nTableMask)))
  330. #define STRTAB_STR_TO_POS(tab, s) \
  331. ((uint32_t)((char*)s - (char*)(tab)))
  332. #define STRTAB_POS_TO_STR(tab, pos) \
  333. ((zend_string*)((char*)(tab) + (pos)))
  334. #define STRTAB_COLLISION(s) \
  335. (*((uint32_t*)((char*)s - sizeof(uint32_t))))
  336. #define STRTAB_STR_SIZE(s) \
  337. ZEND_MM_ALIGNED_SIZE_EX(_ZSTR_HEADER_SIZE + ZSTR_LEN(s) + 5, 8)
  338. #define STRTAB_NEXT(s) \
  339. ((zend_string*)((char*)(s) + STRTAB_STR_SIZE(s)))
  340. static void accel_interned_strings_restore_state(void)
  341. {
  342. zend_string *s, *top;
  343. uint32_t *hash_slot, n;
  344. /* clear removed content */
  345. memset(ZCSG(interned_strings).saved_top,
  346. 0, (char*)ZCSG(interned_strings).top - (char*)ZCSG(interned_strings).saved_top);
  347. /* Reset "top" */
  348. ZCSG(interned_strings).top = ZCSG(interned_strings).saved_top;
  349. /* rehash */
  350. memset((char*)&ZCSG(interned_strings) + sizeof(zend_string_table),
  351. STRTAB_INVALID_POS,
  352. (char*)ZCSG(interned_strings).start -
  353. ((char*)&ZCSG(interned_strings) + sizeof(zend_string_table)));
  354. s = ZCSG(interned_strings).start;
  355. top = ZCSG(interned_strings).top;
  356. n = 0;
  357. if (EXPECTED(s < top)) {
  358. do {
  359. if (ZSTR_HAS_CE_CACHE(s)) {
  360. /* Discard non-global CE_CACHE slots on reset. */
  361. uintptr_t idx = (GC_REFCOUNT(s) - 1) / sizeof(void *);
  362. if (idx >= ZCSG(map_ptr_last)) {
  363. GC_SET_REFCOUNT(s, 2);
  364. GC_DEL_FLAGS(s, IS_STR_CLASS_NAME_MAP_PTR);
  365. }
  366. }
  367. hash_slot = STRTAB_HASH_TO_SLOT(&ZCSG(interned_strings), ZSTR_H(s));
  368. STRTAB_COLLISION(s) = *hash_slot;
  369. *hash_slot = STRTAB_STR_TO_POS(&ZCSG(interned_strings), s);
  370. s = STRTAB_NEXT(s);
  371. n++;
  372. } while (s < top);
  373. }
  374. ZCSG(interned_strings).nNumOfElements = n;
  375. }
  376. static void accel_interned_strings_save_state(void)
  377. {
  378. ZCSG(interned_strings).saved_top = ZCSG(interned_strings).top;
  379. }
  380. static zend_always_inline zend_string *accel_find_interned_string(zend_string *str)
  381. {
  382. zend_ulong h;
  383. uint32_t pos;
  384. zend_string *s;
  385. if (IS_ACCEL_INTERNED(str)) {
  386. /* this is already an interned string */
  387. return str;
  388. }
  389. if (!ZCG(counted)) {
  390. if (!ZCG(accelerator_enabled) || accel_activate_add() == FAILURE) {
  391. return NULL;
  392. }
  393. ZCG(counted) = 1;
  394. }
  395. h = zend_string_hash_val(str);
  396. /* check for existing interned string */
  397. pos = *STRTAB_HASH_TO_SLOT(&ZCSG(interned_strings), h);
  398. if (EXPECTED(pos != STRTAB_INVALID_POS)) {
  399. do {
  400. s = STRTAB_POS_TO_STR(&ZCSG(interned_strings), pos);
  401. if (EXPECTED(ZSTR_H(s) == h) && zend_string_equal_content(s, str)) {
  402. return s;
  403. }
  404. pos = STRTAB_COLLISION(s);
  405. } while (pos != STRTAB_INVALID_POS);
  406. }
  407. return NULL;
  408. }
  409. zend_string* ZEND_FASTCALL accel_new_interned_string(zend_string *str)
  410. {
  411. zend_ulong h;
  412. uint32_t pos, *hash_slot;
  413. zend_string *s;
  414. if (UNEXPECTED(file_cache_only)) {
  415. return str;
  416. }
  417. if (IS_ACCEL_INTERNED(str)) {
  418. /* this is already an interned string */
  419. return str;
  420. }
  421. h = zend_string_hash_val(str);
  422. /* check for existing interned string */
  423. hash_slot = STRTAB_HASH_TO_SLOT(&ZCSG(interned_strings), h);
  424. pos = *hash_slot;
  425. if (EXPECTED(pos != STRTAB_INVALID_POS)) {
  426. do {
  427. s = STRTAB_POS_TO_STR(&ZCSG(interned_strings), pos);
  428. if (EXPECTED(ZSTR_H(s) == h) && zend_string_equal_content(s, str)) {
  429. goto finish;
  430. }
  431. pos = STRTAB_COLLISION(s);
  432. } while (pos != STRTAB_INVALID_POS);
  433. }
  434. if (UNEXPECTED((char*)ZCSG(interned_strings).end - (char*)ZCSG(interned_strings).top < STRTAB_STR_SIZE(str))) {
  435. /* no memory, return the same non-interned string */
  436. zend_accel_error(ACCEL_LOG_WARNING, "Interned string buffer overflow");
  437. return str;
  438. }
  439. /* create new interning string in shared interned strings buffer */
  440. ZCSG(interned_strings).nNumOfElements++;
  441. s = ZCSG(interned_strings).top;
  442. hash_slot = STRTAB_HASH_TO_SLOT(&ZCSG(interned_strings), h);
  443. STRTAB_COLLISION(s) = *hash_slot;
  444. *hash_slot = STRTAB_STR_TO_POS(&ZCSG(interned_strings), s);
  445. GC_SET_REFCOUNT(s, 2);
  446. GC_TYPE_INFO(s) = GC_STRING | ((IS_STR_INTERNED | IS_STR_PERMANENT) << GC_FLAGS_SHIFT);
  447. ZSTR_H(s) = h;
  448. ZSTR_LEN(s) = ZSTR_LEN(str);
  449. memcpy(ZSTR_VAL(s), ZSTR_VAL(str), ZSTR_LEN(s) + 1);
  450. ZCSG(interned_strings).top = STRTAB_NEXT(s);
  451. finish:
  452. /* Transfer CE_CACHE map ptr slot to new interned string.
  453. * Should only happen for permanent interned strings with permanent map_ptr slot. */
  454. if (ZSTR_HAS_CE_CACHE(str) && !ZSTR_HAS_CE_CACHE(s)) {
  455. ZEND_ASSERT(GC_FLAGS(str) & IS_STR_PERMANENT);
  456. GC_SET_REFCOUNT(s, GC_REFCOUNT(str));
  457. GC_ADD_FLAGS(s, IS_STR_CLASS_NAME_MAP_PTR);
  458. }
  459. zend_string_release(str);
  460. return s;
  461. }
  462. static zend_string* ZEND_FASTCALL accel_new_interned_string_for_php(zend_string *str)
  463. {
  464. zend_string_hash_val(str);
  465. if (ZCG(counted)) {
  466. zend_string *ret = accel_find_interned_string(str);
  467. if (ret) {
  468. zend_string_release(str);
  469. return ret;
  470. }
  471. }
  472. return str;
  473. }
  474. static zend_always_inline zend_string *accel_find_interned_string_ex(zend_ulong h, const char *str, size_t size)
  475. {
  476. uint32_t pos;
  477. zend_string *s;
  478. /* check for existing interned string */
  479. pos = *STRTAB_HASH_TO_SLOT(&ZCSG(interned_strings), h);
  480. if (EXPECTED(pos != STRTAB_INVALID_POS)) {
  481. do {
  482. s = STRTAB_POS_TO_STR(&ZCSG(interned_strings), pos);
  483. if (EXPECTED(ZSTR_H(s) == h) && EXPECTED(ZSTR_LEN(s) == size)) {
  484. if (!memcmp(ZSTR_VAL(s), str, size)) {
  485. return s;
  486. }
  487. }
  488. pos = STRTAB_COLLISION(s);
  489. } while (pos != STRTAB_INVALID_POS);
  490. }
  491. return NULL;
  492. }
  493. static zend_string* ZEND_FASTCALL accel_init_interned_string_for_php(const char *str, size_t size, bool permanent)
  494. {
  495. if (ZCG(counted)) {
  496. zend_ulong h = zend_inline_hash_func(str, size);
  497. zend_string *ret = accel_find_interned_string_ex(h, str, size);
  498. if (!ret) {
  499. ret = zend_string_init(str, size, permanent);
  500. ZSTR_H(ret) = h;
  501. }
  502. return ret;
  503. }
  504. return zend_string_init(str, size, permanent);
  505. }
  506. /* Copy PHP interned strings from PHP process memory into the shared memory */
  507. static void accel_copy_permanent_strings(zend_new_interned_string_func_t new_interned_string)
  508. {
  509. uint32_t j;
  510. Bucket *p, *q;
  511. HashTable *ht;
  512. /* empty string */
  513. zend_empty_string = new_interned_string(zend_empty_string);
  514. for (j = 0; j < 256; j++) {
  515. zend_one_char_string[j] = new_interned_string(ZSTR_CHAR(j));
  516. }
  517. for (j = 0; j < ZEND_STR_LAST_KNOWN; j++) {
  518. zend_known_strings[j] = new_interned_string(zend_known_strings[j]);
  519. }
  520. /* function table hash keys */
  521. ZEND_HASH_FOREACH_BUCKET(CG(function_table), p) {
  522. if (p->key) {
  523. p->key = new_interned_string(p->key);
  524. }
  525. if (Z_FUNC(p->val)->common.function_name) {
  526. Z_FUNC(p->val)->common.function_name = new_interned_string(Z_FUNC(p->val)->common.function_name);
  527. }
  528. if (Z_FUNC(p->val)->common.arg_info &&
  529. (Z_FUNC(p->val)->common.fn_flags & (ZEND_ACC_HAS_RETURN_TYPE|ZEND_ACC_HAS_TYPE_HINTS))) {
  530. uint32_t i;
  531. uint32_t num_args = Z_FUNC(p->val)->common.num_args + 1;
  532. zend_arg_info *arg_info = Z_FUNC(p->val)->common.arg_info - 1;
  533. if (Z_FUNC(p->val)->common.fn_flags & ZEND_ACC_VARIADIC) {
  534. num_args++;
  535. }
  536. for (i = 0 ; i < num_args; i++) {
  537. zend_type *single_type;
  538. ZEND_TYPE_FOREACH(arg_info[i].type, single_type) {
  539. if (ZEND_TYPE_HAS_NAME(*single_type)) {
  540. ZEND_TYPE_SET_PTR(*single_type,
  541. new_interned_string(ZEND_TYPE_NAME(*single_type)));
  542. }
  543. } ZEND_TYPE_FOREACH_END();
  544. }
  545. }
  546. } ZEND_HASH_FOREACH_END();
  547. /* class table hash keys, class names, properties, methods, constants, etc */
  548. ZEND_HASH_FOREACH_BUCKET(CG(class_table), p) {
  549. zend_class_entry *ce;
  550. ce = (zend_class_entry*)Z_PTR(p->val);
  551. if (p->key) {
  552. p->key = new_interned_string(p->key);
  553. }
  554. if (ce->name) {
  555. ce->name = new_interned_string(ce->name);
  556. ZEND_ASSERT(ZSTR_HAS_CE_CACHE(ce->name));
  557. }
  558. ZEND_HASH_FOREACH_BUCKET(&ce->properties_info, q) {
  559. zend_property_info *info;
  560. info = (zend_property_info*)Z_PTR(q->val);
  561. if (q->key) {
  562. q->key = new_interned_string(q->key);
  563. }
  564. if (info->name) {
  565. info->name = new_interned_string(info->name);
  566. }
  567. } ZEND_HASH_FOREACH_END();
  568. ZEND_HASH_FOREACH_BUCKET(&ce->function_table, q) {
  569. if (q->key) {
  570. q->key = new_interned_string(q->key);
  571. }
  572. if (Z_FUNC(q->val)->common.function_name) {
  573. Z_FUNC(q->val)->common.function_name = new_interned_string(Z_FUNC(q->val)->common.function_name);
  574. }
  575. } ZEND_HASH_FOREACH_END();
  576. ZEND_HASH_FOREACH_BUCKET(&ce->constants_table, q) {
  577. zend_class_constant* c;
  578. if (q->key) {
  579. q->key = new_interned_string(q->key);
  580. }
  581. c = (zend_class_constant*)Z_PTR(q->val);
  582. if (Z_TYPE(c->value) == IS_STRING) {
  583. ZVAL_STR(&c->value, new_interned_string(Z_STR(c->value)));
  584. }
  585. } ZEND_HASH_FOREACH_END();
  586. } ZEND_HASH_FOREACH_END();
  587. /* constant hash keys */
  588. ZEND_HASH_FOREACH_BUCKET(EG(zend_constants), p) {
  589. zend_constant *c;
  590. if (p->key) {
  591. p->key = new_interned_string(p->key);
  592. }
  593. c = (zend_constant*)Z_PTR(p->val);
  594. if (c->name) {
  595. c->name = new_interned_string(c->name);
  596. }
  597. if (Z_TYPE(c->value) == IS_STRING) {
  598. ZVAL_STR(&c->value, new_interned_string(Z_STR(c->value)));
  599. }
  600. } ZEND_HASH_FOREACH_END();
  601. /* auto globals hash keys and names */
  602. ZEND_HASH_FOREACH_BUCKET(CG(auto_globals), p) {
  603. zend_auto_global *auto_global;
  604. auto_global = (zend_auto_global*)Z_PTR(p->val);
  605. zend_string_addref(auto_global->name);
  606. auto_global->name = new_interned_string(auto_global->name);
  607. if (p->key) {
  608. p->key = new_interned_string(p->key);
  609. }
  610. } ZEND_HASH_FOREACH_END();
  611. ZEND_HASH_FOREACH_BUCKET(&module_registry, p) {
  612. if (p->key) {
  613. p->key = new_interned_string(p->key);
  614. }
  615. } ZEND_HASH_FOREACH_END();
  616. ZEND_HASH_FOREACH_BUCKET(EG(ini_directives), p) {
  617. zend_ini_entry *entry = (zend_ini_entry*)Z_PTR(p->val);
  618. if (p->key) {
  619. p->key = new_interned_string(p->key);
  620. }
  621. if (entry->name) {
  622. entry->name = new_interned_string(entry->name);
  623. }
  624. if (entry->value) {
  625. entry->value = new_interned_string(entry->value);
  626. }
  627. if (entry->orig_value) {
  628. entry->orig_value = new_interned_string(entry->orig_value);
  629. }
  630. } ZEND_HASH_FOREACH_END();
  631. ht = php_get_stream_filters_hash_global();
  632. ZEND_HASH_FOREACH_BUCKET(ht, p) {
  633. if (p->key) {
  634. p->key = new_interned_string(p->key);
  635. }
  636. } ZEND_HASH_FOREACH_END();
  637. ht = php_stream_get_url_stream_wrappers_hash_global();
  638. ZEND_HASH_FOREACH_BUCKET(ht, p) {
  639. if (p->key) {
  640. p->key = new_interned_string(p->key);
  641. }
  642. } ZEND_HASH_FOREACH_END();
  643. ht = php_stream_xport_get_hash();
  644. ZEND_HASH_FOREACH_BUCKET(ht, p) {
  645. if (p->key) {
  646. p->key = new_interned_string(p->key);
  647. }
  648. } ZEND_HASH_FOREACH_END();
  649. }
  650. static zend_string* ZEND_FASTCALL accel_replace_string_by_shm_permanent(zend_string *str)
  651. {
  652. zend_string *ret = accel_find_interned_string(str);
  653. if (ret) {
  654. zend_string_release(str);
  655. return ret;
  656. }
  657. return str;
  658. }
  659. static void accel_use_shm_interned_strings(void)
  660. {
  661. HANDLE_BLOCK_INTERRUPTIONS();
  662. SHM_UNPROTECT();
  663. zend_shared_alloc_lock();
  664. if (ZCSG(interned_strings).saved_top == NULL) {
  665. accel_copy_permanent_strings(accel_new_interned_string);
  666. } else {
  667. ZCG(counted) = 1;
  668. accel_copy_permanent_strings(accel_replace_string_by_shm_permanent);
  669. ZCG(counted) = 0;
  670. }
  671. accel_interned_strings_save_state();
  672. zend_shared_alloc_unlock();
  673. SHM_PROTECT();
  674. HANDLE_UNBLOCK_INTERRUPTIONS();
  675. }
  676. #ifndef ZEND_WIN32
  677. static inline void kill_all_lockers(struct flock *mem_usage_check)
  678. {
  679. int success, tries;
  680. /* so that other process won't try to force while we are busy cleaning up */
  681. ZCSG(force_restart_time) = 0;
  682. while (mem_usage_check->l_pid > 0) {
  683. /* Try SIGTERM first, switch to SIGKILL if not successful. */
  684. int signal = SIGTERM;
  685. errno = 0;
  686. success = 0;
  687. tries = 10;
  688. while (tries--) {
  689. zend_accel_error(ACCEL_LOG_WARNING, "Attempting to kill locker %d", mem_usage_check->l_pid);
  690. if (kill(mem_usage_check->l_pid, signal)) {
  691. if (errno == ESRCH) {
  692. /* Process died before the signal was sent */
  693. success = 1;
  694. zend_accel_error(ACCEL_LOG_WARNING, "Process %d died before SIGKILL was sent", mem_usage_check->l_pid);
  695. } else if (errno != 0) {
  696. zend_accel_error(ACCEL_LOG_WARNING, "Failed to send SIGKILL to locker %d: %s", mem_usage_check->l_pid, strerror(errno));
  697. }
  698. break;
  699. }
  700. /* give it a chance to die */
  701. usleep(20000);
  702. if (kill(mem_usage_check->l_pid, 0)) {
  703. if (errno == ESRCH) {
  704. /* successfully killed locker, process no longer exists */
  705. success = 1;
  706. zend_accel_error(ACCEL_LOG_WARNING, "Killed locker %d", mem_usage_check->l_pid);
  707. } else if (errno != 0) {
  708. zend_accel_error(ACCEL_LOG_WARNING, "Failed to check locker %d: %s", mem_usage_check->l_pid, strerror(errno));
  709. }
  710. break;
  711. }
  712. usleep(10000);
  713. /* If SIGTERM was not sufficient, use SIGKILL. */
  714. signal = SIGKILL;
  715. }
  716. if (!success) {
  717. /* errno is not ESRCH or we ran out of tries to kill the locker */
  718. ZCSG(force_restart_time) = time(NULL); /* restore forced restart request */
  719. /* cannot kill the locker, bail out with error */
  720. zend_accel_error_noreturn(ACCEL_LOG_ERROR, "Cannot kill process %d!", mem_usage_check->l_pid);
  721. }
  722. mem_usage_check->l_type = F_WRLCK;
  723. mem_usage_check->l_whence = SEEK_SET;
  724. mem_usage_check->l_start = 1;
  725. mem_usage_check->l_len = 1;
  726. mem_usage_check->l_pid = -1;
  727. if (fcntl(lock_file, F_GETLK, mem_usage_check) == -1) {
  728. zend_accel_error(ACCEL_LOG_DEBUG, "KLockers: %s (%d)", strerror(errno), errno);
  729. break;
  730. }
  731. if (mem_usage_check->l_type == F_UNLCK || mem_usage_check->l_pid <= 0) {
  732. break;
  733. }
  734. }
  735. }
  736. #endif
  737. static inline int accel_is_inactive(void)
  738. {
  739. #ifdef ZEND_WIN32
  740. if (LOCKVAL(mem_usage) == 0) {
  741. return SUCCESS;
  742. }
  743. #else
  744. struct flock mem_usage_check;
  745. mem_usage_check.l_type = F_WRLCK;
  746. mem_usage_check.l_whence = SEEK_SET;
  747. mem_usage_check.l_start = 1;
  748. mem_usage_check.l_len = 1;
  749. mem_usage_check.l_pid = -1;
  750. if (fcntl(lock_file, F_GETLK, &mem_usage_check) == -1) {
  751. zend_accel_error(ACCEL_LOG_DEBUG, "UpdateC: %s (%d)", strerror(errno), errno);
  752. return FAILURE;
  753. }
  754. if (mem_usage_check.l_type == F_UNLCK) {
  755. return SUCCESS;
  756. }
  757. if (ZCG(accel_directives).force_restart_timeout
  758. && ZCSG(force_restart_time)
  759. && time(NULL) >= ZCSG(force_restart_time)) {
  760. 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);
  761. kill_all_lockers(&mem_usage_check);
  762. return FAILURE; /* next request should be able to restart it */
  763. }
  764. #endif
  765. return FAILURE;
  766. }
  767. static int zend_get_stream_timestamp(const char *filename, zend_stat_t *statbuf)
  768. {
  769. php_stream_wrapper *wrapper;
  770. php_stream_statbuf stream_statbuf;
  771. int ret, er;
  772. if (!filename) {
  773. return FAILURE;
  774. }
  775. wrapper = php_stream_locate_url_wrapper(filename, NULL, STREAM_LOCATE_WRAPPERS_ONLY);
  776. if (!wrapper) {
  777. return FAILURE;
  778. }
  779. if (!wrapper->wops || !wrapper->wops->url_stat) {
  780. statbuf->st_mtime = 1;
  781. return SUCCESS; /* anything other than 0 is considered to be a valid timestamp */
  782. }
  783. er = EG(error_reporting);
  784. EG(error_reporting) = 0;
  785. zend_try {
  786. ret = wrapper->wops->url_stat(wrapper, (char*)filename, PHP_STREAM_URL_STAT_QUIET, &stream_statbuf, NULL);
  787. } zend_catch {
  788. ret = -1;
  789. } zend_end_try();
  790. EG(error_reporting) = er;
  791. if (ret != 0) {
  792. return FAILURE;
  793. }
  794. *statbuf = stream_statbuf.sb;
  795. return SUCCESS;
  796. }
  797. #if ZEND_WIN32
  798. static accel_time_t zend_get_file_handle_timestamp_win(zend_file_handle *file_handle, size_t *size)
  799. {
  800. static unsigned __int64 utc_base = 0;
  801. static FILETIME utc_base_ft;
  802. WIN32_FILE_ATTRIBUTE_DATA fdata;
  803. if (!file_handle->opened_path) {
  804. return 0;
  805. }
  806. if (!utc_base) {
  807. SYSTEMTIME st;
  808. st.wYear = 1970;
  809. st.wMonth = 1;
  810. st.wDay = 1;
  811. st.wHour = 0;
  812. st.wMinute = 0;
  813. st.wSecond = 0;
  814. st.wMilliseconds = 0;
  815. SystemTimeToFileTime (&st, &utc_base_ft);
  816. utc_base = (((unsigned __int64)utc_base_ft.dwHighDateTime) << 32) + utc_base_ft.dwLowDateTime;
  817. }
  818. if (file_handle->opened_path && GetFileAttributesEx(file_handle->opened_path->val, GetFileExInfoStandard, &fdata) != 0) {
  819. unsigned __int64 ftime;
  820. if (CompareFileTime (&fdata.ftLastWriteTime, &utc_base_ft) < 0) {
  821. return 0;
  822. }
  823. ftime = (((unsigned __int64)fdata.ftLastWriteTime.dwHighDateTime) << 32) + fdata.ftLastWriteTime.dwLowDateTime - utc_base;
  824. ftime /= 10000000L;
  825. if (size) {
  826. *size = (size_t)((((unsigned __int64)fdata.nFileSizeHigh) << 32) + (unsigned __int64)fdata.nFileSizeLow);
  827. }
  828. return (accel_time_t)ftime;
  829. }
  830. return 0;
  831. }
  832. #endif
  833. accel_time_t zend_get_file_handle_timestamp(zend_file_handle *file_handle, size_t *size)
  834. {
  835. zend_stat_t statbuf;
  836. #ifdef ZEND_WIN32
  837. accel_time_t res;
  838. #endif
  839. if (sapi_module.get_stat &&
  840. !EG(current_execute_data) &&
  841. file_handle->primary_script) {
  842. zend_stat_t *tmpbuf = sapi_module.get_stat();
  843. if (tmpbuf) {
  844. if (size) {
  845. *size = tmpbuf->st_size;
  846. }
  847. return tmpbuf->st_mtime;
  848. }
  849. }
  850. #ifdef ZEND_WIN32
  851. res = zend_get_file_handle_timestamp_win(file_handle, size);
  852. if (res) {
  853. return res;
  854. }
  855. #endif
  856. switch (file_handle->type) {
  857. case ZEND_HANDLE_FP:
  858. if (zend_fstat(fileno(file_handle->handle.fp), &statbuf) == -1) {
  859. if (zend_get_stream_timestamp(ZSTR_VAL(file_handle->filename), &statbuf) != SUCCESS) {
  860. return 0;
  861. }
  862. }
  863. break;
  864. case ZEND_HANDLE_FILENAME:
  865. if (file_handle->opened_path) {
  866. char *file_path = ZSTR_VAL(file_handle->opened_path);
  867. if (is_stream_path(file_path)) {
  868. if (zend_get_stream_timestamp(file_path, &statbuf) == SUCCESS) {
  869. break;
  870. }
  871. }
  872. if (VCWD_STAT(file_path, &statbuf) != -1) {
  873. break;
  874. }
  875. }
  876. if (zend_get_stream_timestamp(ZSTR_VAL(file_handle->filename), &statbuf) != SUCCESS) {
  877. return 0;
  878. }
  879. break;
  880. case ZEND_HANDLE_STREAM:
  881. {
  882. php_stream *stream = (php_stream *)file_handle->handle.stream.handle;
  883. php_stream_statbuf sb;
  884. int ret, er;
  885. if (!stream ||
  886. !stream->ops ||
  887. !stream->ops->stat) {
  888. return 0;
  889. }
  890. er = EG(error_reporting);
  891. EG(error_reporting) = 0;
  892. zend_try {
  893. ret = stream->ops->stat(stream, &sb);
  894. } zend_catch {
  895. ret = -1;
  896. } zend_end_try();
  897. EG(error_reporting) = er;
  898. if (ret != 0) {
  899. return 0;
  900. }
  901. statbuf = sb.sb;
  902. }
  903. break;
  904. default:
  905. return 0;
  906. }
  907. if (size) {
  908. *size = statbuf.st_size;
  909. }
  910. return statbuf.st_mtime;
  911. }
  912. static inline int do_validate_timestamps(zend_persistent_script *persistent_script, zend_file_handle *file_handle)
  913. {
  914. zend_file_handle ps_handle;
  915. zend_string *full_path_ptr = NULL;
  916. int ret;
  917. /** check that the persistent script is indeed the same file we cached
  918. * (if part of the path is a symlink than it possible that the user will change it)
  919. * See bug #15140
  920. */
  921. if (file_handle->opened_path) {
  922. if (persistent_script->script.filename != file_handle->opened_path &&
  923. !zend_string_equal_content(persistent_script->script.filename, file_handle->opened_path)) {
  924. return FAILURE;
  925. }
  926. } else {
  927. full_path_ptr = accelerator_orig_zend_resolve_path(file_handle->filename);
  928. if (full_path_ptr &&
  929. persistent_script->script.filename != full_path_ptr &&
  930. !zend_string_equal_content(persistent_script->script.filename, full_path_ptr)) {
  931. zend_string_release_ex(full_path_ptr, 0);
  932. return FAILURE;
  933. }
  934. file_handle->opened_path = full_path_ptr;
  935. }
  936. if (persistent_script->timestamp == 0) {
  937. if (full_path_ptr) {
  938. zend_string_release_ex(full_path_ptr, 0);
  939. file_handle->opened_path = NULL;
  940. }
  941. return FAILURE;
  942. }
  943. if (zend_get_file_handle_timestamp(file_handle, NULL) == persistent_script->timestamp) {
  944. if (full_path_ptr) {
  945. zend_string_release_ex(full_path_ptr, 0);
  946. file_handle->opened_path = NULL;
  947. }
  948. return SUCCESS;
  949. }
  950. if (full_path_ptr) {
  951. zend_string_release_ex(full_path_ptr, 0);
  952. file_handle->opened_path = NULL;
  953. }
  954. zend_stream_init_filename_ex(&ps_handle, persistent_script->script.filename);
  955. ps_handle.opened_path = persistent_script->script.filename;
  956. ret = zend_get_file_handle_timestamp(&ps_handle, NULL) == persistent_script->timestamp
  957. ? SUCCESS : FAILURE;
  958. zend_destroy_file_handle(&ps_handle);
  959. return ret;
  960. }
  961. int validate_timestamp_and_record(zend_persistent_script *persistent_script, zend_file_handle *file_handle)
  962. {
  963. if (persistent_script->timestamp == 0) {
  964. return SUCCESS; /* Don't check timestamps of preloaded scripts */
  965. } else if (ZCG(accel_directives).revalidate_freq &&
  966. persistent_script->dynamic_members.revalidate >= ZCG(request_time)) {
  967. return SUCCESS;
  968. } else if (do_validate_timestamps(persistent_script, file_handle) == FAILURE) {
  969. return FAILURE;
  970. } else {
  971. persistent_script->dynamic_members.revalidate = ZCG(request_time) + ZCG(accel_directives).revalidate_freq;
  972. return SUCCESS;
  973. }
  974. }
  975. int validate_timestamp_and_record_ex(zend_persistent_script *persistent_script, zend_file_handle *file_handle)
  976. {
  977. int ret;
  978. SHM_UNPROTECT();
  979. ret = validate_timestamp_and_record(persistent_script, file_handle);
  980. SHM_PROTECT();
  981. return ret;
  982. }
  983. /* Instead of resolving full real path name each time we need to identify file,
  984. * we create a key that consist from requested file name, current working
  985. * directory, current include_path, etc */
  986. zend_string *accel_make_persistent_key(zend_string *str)
  987. {
  988. const char *path = ZSTR_VAL(str);
  989. size_t path_length = ZSTR_LEN(str);
  990. char *key;
  991. int key_length;
  992. ZSTR_LEN(&ZCG(key)) = 0;
  993. /* CWD and include_path don't matter for absolute file names and streams */
  994. if (IS_ABSOLUTE_PATH(path, path_length)) {
  995. /* pass */
  996. } else if (UNEXPECTED(is_stream_path(path))) {
  997. if (!is_cacheable_stream_path(path)) {
  998. return NULL;
  999. }
  1000. /* pass */
  1001. } else if (UNEXPECTED(!ZCG(accel_directives).use_cwd)) {
  1002. /* pass */
  1003. } else {
  1004. const char *include_path = NULL, *cwd = NULL;
  1005. int include_path_len = 0, cwd_len = 0;
  1006. zend_string *parent_script = NULL;
  1007. size_t parent_script_len = 0;
  1008. if (EXPECTED(ZCG(cwd_key_len))) {
  1009. cwd = ZCG(cwd_key);
  1010. cwd_len = ZCG(cwd_key_len);
  1011. } else {
  1012. zend_string *cwd_str = accel_getcwd();
  1013. if (UNEXPECTED(!cwd_str)) {
  1014. /* we don't handle this well for now. */
  1015. 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);
  1016. return NULL;
  1017. }
  1018. cwd = ZSTR_VAL(cwd_str);
  1019. cwd_len = ZSTR_LEN(cwd_str);
  1020. if (ZCG(cwd_check)) {
  1021. ZCG(cwd_check) = 0;
  1022. if (ZCG(accelerator_enabled)) {
  1023. zend_string *str = accel_find_interned_string(cwd_str);
  1024. if (!str) {
  1025. HANDLE_BLOCK_INTERRUPTIONS();
  1026. SHM_UNPROTECT();
  1027. zend_shared_alloc_lock();
  1028. str = accel_new_interned_string(zend_string_copy(cwd_str));
  1029. if (str == cwd_str) {
  1030. zend_string_release_ex(str, 0);
  1031. str = NULL;
  1032. }
  1033. zend_shared_alloc_unlock();
  1034. SHM_PROTECT();
  1035. HANDLE_UNBLOCK_INTERRUPTIONS();
  1036. }
  1037. if (str) {
  1038. char buf[32];
  1039. char *res = zend_print_long_to_buf(buf + sizeof(buf) - 1, STRTAB_STR_TO_POS(&ZCSG(interned_strings), str));
  1040. cwd_len = ZCG(cwd_key_len) = buf + sizeof(buf) - 1 - res;
  1041. cwd = ZCG(cwd_key);
  1042. memcpy(ZCG(cwd_key), res, cwd_len + 1);
  1043. } else {
  1044. return NULL;
  1045. }
  1046. } else {
  1047. return NULL;
  1048. }
  1049. }
  1050. }
  1051. if (EXPECTED(ZCG(include_path_key_len))) {
  1052. include_path = ZCG(include_path_key);
  1053. include_path_len = ZCG(include_path_key_len);
  1054. } else if (!ZCG(include_path) || ZSTR_LEN(ZCG(include_path)) == 0) {
  1055. include_path = "";
  1056. include_path_len = 0;
  1057. } else {
  1058. include_path = ZSTR_VAL(ZCG(include_path));
  1059. include_path_len = ZSTR_LEN(ZCG(include_path));
  1060. if (ZCG(include_path_check)) {
  1061. ZCG(include_path_check) = 0;
  1062. if (ZCG(accelerator_enabled)) {
  1063. zend_string *str = accel_find_interned_string(ZCG(include_path));
  1064. if (!str) {
  1065. HANDLE_BLOCK_INTERRUPTIONS();
  1066. SHM_UNPROTECT();
  1067. zend_shared_alloc_lock();
  1068. str = accel_new_interned_string(zend_string_copy(ZCG(include_path)));
  1069. if (str == ZCG(include_path)) {
  1070. zend_string_release(str);
  1071. str = NULL;
  1072. }
  1073. zend_shared_alloc_unlock();
  1074. SHM_PROTECT();
  1075. HANDLE_UNBLOCK_INTERRUPTIONS();
  1076. }
  1077. if (str) {
  1078. char buf[32];
  1079. char *res = zend_print_long_to_buf(buf + sizeof(buf) - 1, STRTAB_STR_TO_POS(&ZCSG(interned_strings), str));
  1080. include_path_len = ZCG(include_path_key_len) = buf + sizeof(buf) - 1 - res;
  1081. include_path = ZCG(include_path_key);
  1082. memcpy(ZCG(include_path_key), res, include_path_len + 1);
  1083. } else {
  1084. return NULL;
  1085. }
  1086. } else {
  1087. return NULL;
  1088. }
  1089. }
  1090. }
  1091. /* Calculate key length */
  1092. if (UNEXPECTED((size_t)(cwd_len + path_length + include_path_len + 2) >= sizeof(ZCG(_key)))) {
  1093. return NULL;
  1094. }
  1095. /* Generate key
  1096. * Note - the include_path must be the last element in the key,
  1097. * since in itself, it may include colons (which we use to separate
  1098. * different components of the key)
  1099. */
  1100. key = ZSTR_VAL(&ZCG(key));
  1101. memcpy(key, path, path_length);
  1102. key[path_length] = ':';
  1103. key_length = path_length + 1;
  1104. memcpy(key + key_length, cwd, cwd_len);
  1105. key_length += cwd_len;
  1106. if (include_path_len) {
  1107. key[key_length] = ':';
  1108. key_length += 1;
  1109. memcpy(key + key_length, include_path, include_path_len);
  1110. key_length += include_path_len;
  1111. }
  1112. /* Here we add to the key the parent script directory,
  1113. * since fopen_wrappers from version 4.0.7 use current script's path
  1114. * in include path too.
  1115. */
  1116. if (EXPECTED(EG(current_execute_data)) &&
  1117. EXPECTED((parent_script = zend_get_executed_filename_ex()) != NULL)) {
  1118. parent_script_len = ZSTR_LEN(parent_script);
  1119. while ((--parent_script_len > 0) && !IS_SLASH(ZSTR_VAL(parent_script)[parent_script_len]));
  1120. if (UNEXPECTED((size_t)(key_length + parent_script_len + 1) >= sizeof(ZCG(_key)))) {
  1121. return NULL;
  1122. }
  1123. key[key_length] = ':';
  1124. key_length += 1;
  1125. memcpy(key + key_length, ZSTR_VAL(parent_script), parent_script_len);
  1126. key_length += parent_script_len;
  1127. }
  1128. key[key_length] = '\0';
  1129. GC_SET_REFCOUNT(&ZCG(key), 1);
  1130. GC_TYPE_INFO(&ZCG(key)) = GC_STRING;
  1131. ZSTR_H(&ZCG(key)) = 0;
  1132. ZSTR_LEN(&ZCG(key)) = key_length;
  1133. return &ZCG(key);
  1134. }
  1135. /* not use_cwd */
  1136. return str;
  1137. }
  1138. int zend_accel_invalidate(zend_string *filename, bool force)
  1139. {
  1140. zend_string *realpath;
  1141. zend_persistent_script *persistent_script;
  1142. if (!ZCG(accelerator_enabled) || accelerator_shm_read_lock() != SUCCESS) {
  1143. return FAILURE;
  1144. }
  1145. realpath = accelerator_orig_zend_resolve_path(filename);
  1146. if (!realpath) {
  1147. return FAILURE;
  1148. }
  1149. if (ZCG(accel_directives).file_cache) {
  1150. zend_file_cache_invalidate(realpath);
  1151. }
  1152. persistent_script = zend_accel_hash_find(&ZCSG(hash), realpath);
  1153. if (persistent_script && !persistent_script->corrupted) {
  1154. zend_file_handle file_handle;
  1155. zend_stream_init_filename_ex(&file_handle, realpath);
  1156. file_handle.opened_path = realpath;
  1157. if (force ||
  1158. !ZCG(accel_directives).validate_timestamps ||
  1159. do_validate_timestamps(persistent_script, &file_handle) == FAILURE) {
  1160. HANDLE_BLOCK_INTERRUPTIONS();
  1161. SHM_UNPROTECT();
  1162. zend_shared_alloc_lock();
  1163. if (!persistent_script->corrupted) {
  1164. persistent_script->corrupted = 1;
  1165. persistent_script->timestamp = 0;
  1166. ZSMMG(wasted_shared_memory) += persistent_script->dynamic_members.memory_consumption;
  1167. if (ZSMMG(memory_exhausted)) {
  1168. zend_accel_restart_reason reason =
  1169. zend_accel_hash_is_full(&ZCSG(hash)) ? ACCEL_RESTART_HASH : ACCEL_RESTART_OOM;
  1170. zend_accel_schedule_restart_if_necessary(reason);
  1171. }
  1172. }
  1173. zend_shared_alloc_unlock();
  1174. SHM_PROTECT();
  1175. HANDLE_UNBLOCK_INTERRUPTIONS();
  1176. }
  1177. file_handle.opened_path = NULL;
  1178. zend_destroy_file_handle(&file_handle);
  1179. }
  1180. accelerator_shm_read_unlock();
  1181. zend_string_release_ex(realpath, 0);
  1182. return SUCCESS;
  1183. }
  1184. static zend_string* accel_new_interned_key(zend_string *key)
  1185. {
  1186. zend_string *new_key;
  1187. if (zend_accel_in_shm(key)) {
  1188. return key;
  1189. }
  1190. GC_ADDREF(key);
  1191. new_key = accel_new_interned_string(key);
  1192. if (UNEXPECTED(new_key == key)) {
  1193. GC_DELREF(key);
  1194. new_key = zend_shared_alloc(ZEND_MM_ALIGNED_SIZE_EX(_ZSTR_STRUCT_SIZE(ZSTR_LEN(key)), 8));
  1195. if (EXPECTED(new_key)) {
  1196. GC_SET_REFCOUNT(new_key, 2);
  1197. GC_TYPE_INFO(new_key) = GC_STRING | (IS_STR_INTERNED << GC_FLAGS_SHIFT);
  1198. ZSTR_H(new_key) = ZSTR_H(key);
  1199. ZSTR_LEN(new_key) = ZSTR_LEN(key);
  1200. memcpy(ZSTR_VAL(new_key), ZSTR_VAL(key), ZSTR_LEN(new_key) + 1);
  1201. }
  1202. }
  1203. return new_key;
  1204. }
  1205. /* Adds another key for existing cached script */
  1206. static void zend_accel_add_key(zend_string *key, zend_accel_hash_entry *bucket)
  1207. {
  1208. if (!zend_accel_hash_find(&ZCSG(hash), key)) {
  1209. if (zend_accel_hash_is_full(&ZCSG(hash))) {
  1210. zend_accel_error(ACCEL_LOG_DEBUG, "No more entries in hash table!");
  1211. ZSMMG(memory_exhausted) = 1;
  1212. zend_accel_schedule_restart_if_necessary(ACCEL_RESTART_HASH);
  1213. } else {
  1214. zend_string *new_key = accel_new_interned_key(key);
  1215. if (new_key) {
  1216. if (zend_accel_hash_update(&ZCSG(hash), new_key, 1, bucket)) {
  1217. zend_accel_error(ACCEL_LOG_INFO, "Added key '%s'", ZSTR_VAL(new_key));
  1218. }
  1219. } else {
  1220. zend_accel_schedule_restart_if_necessary(ACCEL_RESTART_OOM);
  1221. }
  1222. }
  1223. }
  1224. }
  1225. static zend_always_inline bool is_phar_file(zend_string *filename)
  1226. {
  1227. return filename && ZSTR_LEN(filename) >= sizeof(".phar") &&
  1228. !memcmp(ZSTR_VAL(filename) + ZSTR_LEN(filename) - (sizeof(".phar")-1), ".phar", sizeof(".phar")-1) &&
  1229. !strstr(ZSTR_VAL(filename), "://");
  1230. }
  1231. static zend_persistent_script *store_script_in_file_cache(zend_persistent_script *new_persistent_script)
  1232. {
  1233. uint32_t memory_used;
  1234. zend_shared_alloc_init_xlat_table();
  1235. /* Calculate the required memory size */
  1236. memory_used = zend_accel_script_persist_calc(new_persistent_script, 0);
  1237. /* Allocate memory block */
  1238. #if defined(__AVX__) || defined(__SSE2__)
  1239. /* Align to 64-byte boundary */
  1240. ZCG(mem) = zend_arena_alloc(&CG(arena), memory_used + 64);
  1241. ZCG(mem) = (void*)(((zend_uintptr_t)ZCG(mem) + 63L) & ~63L);
  1242. #elif ZEND_MM_ALIGNMENT < 8
  1243. /* Align to 8-byte boundary */
  1244. ZCG(mem) = zend_arena_alloc(&CG(arena), memory_used + 8);
  1245. ZCG(mem) = (void*)(((zend_uintptr_t)ZCG(mem) + 7L) & ~7L);
  1246. #else
  1247. ZCG(mem) = zend_arena_alloc(&CG(arena), memory_used);
  1248. #endif
  1249. zend_shared_alloc_clear_xlat_table();
  1250. /* Copy into memory block */
  1251. new_persistent_script = zend_accel_script_persist(new_persistent_script, 0);
  1252. zend_shared_alloc_destroy_xlat_table();
  1253. new_persistent_script->is_phar = is_phar_file(new_persistent_script->script.filename);
  1254. /* Consistency check */
  1255. if ((char*)new_persistent_script->mem + new_persistent_script->size != (char*)ZCG(mem)) {
  1256. zend_accel_error(
  1257. ((char*)new_persistent_script->mem + new_persistent_script->size < (char*)ZCG(mem)) ? ACCEL_LOG_ERROR : ACCEL_LOG_WARNING,
  1258. "Internal error: wrong size calculation: %s start=" ZEND_ADDR_FMT ", end=" ZEND_ADDR_FMT ", real=" ZEND_ADDR_FMT "\n",
  1259. ZSTR_VAL(new_persistent_script->script.filename),
  1260. (size_t)new_persistent_script->mem,
  1261. (size_t)((char *)new_persistent_script->mem + new_persistent_script->size),
  1262. (size_t)ZCG(mem));
  1263. }
  1264. new_persistent_script->dynamic_members.checksum = zend_accel_script_checksum(new_persistent_script);
  1265. zend_file_cache_script_store(new_persistent_script, 0);
  1266. return new_persistent_script;
  1267. }
  1268. static zend_persistent_script *cache_script_in_file_cache(zend_persistent_script *new_persistent_script, int *from_shared_memory)
  1269. {
  1270. uint32_t orig_compiler_options;
  1271. orig_compiler_options = CG(compiler_options);
  1272. CG(compiler_options) |= ZEND_COMPILE_WITH_FILE_CACHE;
  1273. if (!zend_optimize_script(&new_persistent_script->script, ZCG(accel_directives).optimization_level, ZCG(accel_directives).opt_debug_level)) {
  1274. CG(compiler_options) = orig_compiler_options;
  1275. return new_persistent_script;
  1276. }
  1277. CG(compiler_options) = orig_compiler_options;
  1278. *from_shared_memory = 1;
  1279. return store_script_in_file_cache(new_persistent_script);
  1280. }
  1281. static zend_persistent_script *cache_script_in_shared_memory(zend_persistent_script *new_persistent_script, zend_string *key, int *from_shared_memory)
  1282. {
  1283. zend_accel_hash_entry *bucket;
  1284. uint32_t memory_used;
  1285. uint32_t orig_compiler_options;
  1286. orig_compiler_options = CG(compiler_options);
  1287. if (ZCG(accel_directives).file_cache) {
  1288. CG(compiler_options) |= ZEND_COMPILE_WITH_FILE_CACHE;
  1289. }
  1290. if (!zend_optimize_script(&new_persistent_script->script, ZCG(accel_directives).optimization_level, ZCG(accel_directives).opt_debug_level)) {
  1291. CG(compiler_options) = orig_compiler_options;
  1292. return new_persistent_script;
  1293. }
  1294. CG(compiler_options) = orig_compiler_options;
  1295. /* exclusive lock */
  1296. zend_shared_alloc_lock();
  1297. /* Check if we still need to put the file into the cache (may be it was
  1298. * already stored by another process. This final check is done under
  1299. * exclusive lock) */
  1300. bucket = zend_accel_hash_find_entry(&ZCSG(hash), new_persistent_script->script.filename);
  1301. if (bucket) {
  1302. zend_persistent_script *existing_persistent_script = (zend_persistent_script *)bucket->data;
  1303. if (!existing_persistent_script->corrupted) {
  1304. if (key &&
  1305. (!ZCG(accel_directives).validate_timestamps ||
  1306. (new_persistent_script->timestamp == existing_persistent_script->timestamp))) {
  1307. zend_accel_add_key(key, bucket);
  1308. }
  1309. zend_shared_alloc_unlock();
  1310. #if 1
  1311. /* prefer the script already stored in SHM */
  1312. free_persistent_script(new_persistent_script, 1);
  1313. *from_shared_memory = 1;
  1314. return existing_persistent_script;
  1315. #else
  1316. return new_persistent_script;
  1317. #endif
  1318. }
  1319. }
  1320. if (zend_accel_hash_is_full(&ZCSG(hash))) {
  1321. zend_accel_error(ACCEL_LOG_DEBUG, "No more entries in hash table!");
  1322. ZSMMG(memory_exhausted) = 1;
  1323. zend_accel_schedule_restart_if_necessary(ACCEL_RESTART_HASH);
  1324. zend_shared_alloc_unlock();
  1325. if (ZCG(accel_directives).file_cache) {
  1326. new_persistent_script = store_script_in_file_cache(new_persistent_script);
  1327. *from_shared_memory = 1;
  1328. }
  1329. return new_persistent_script;
  1330. }
  1331. zend_shared_alloc_init_xlat_table();
  1332. /* Calculate the required memory size */
  1333. memory_used = zend_accel_script_persist_calc(new_persistent_script, 1);
  1334. /* Allocate shared memory */
  1335. #if defined(__AVX__) || defined(__SSE2__)
  1336. /* Align to 64-byte boundary */
  1337. ZCG(mem) = zend_shared_alloc(memory_used + 64);
  1338. if (ZCG(mem)) {
  1339. ZCG(mem) = (void*)(((zend_uintptr_t)ZCG(mem) + 63L) & ~63L);
  1340. #if defined(__x86_64__)
  1341. memset(ZCG(mem), 0, memory_used);
  1342. #elif defined(__AVX__)
  1343. {
  1344. char *p = (char*)ZCG(mem);
  1345. char *end = p + memory_used;
  1346. __m256i ymm0 = _mm256_setzero_si256();
  1347. while (p < end) {
  1348. _mm256_store_si256((__m256i*)p, ymm0);
  1349. _mm256_store_si256((__m256i*)(p+32), ymm0);
  1350. p += 64;
  1351. }
  1352. }
  1353. #else
  1354. {
  1355. char *p = (char*)ZCG(mem);
  1356. char *end = p + memory_used;
  1357. __m128i xmm0 = _mm_setzero_si128();
  1358. while (p < end) {
  1359. _mm_store_si128((__m128i*)p, xmm0);
  1360. _mm_store_si128((__m128i*)(p+16), xmm0);
  1361. _mm_store_si128((__m128i*)(p+32), xmm0);
  1362. _mm_store_si128((__m128i*)(p+48), xmm0);
  1363. p += 64;
  1364. }
  1365. }
  1366. #endif
  1367. }
  1368. #else
  1369. ZCG(mem) = zend_shared_alloc(memory_used);
  1370. if (ZCG(mem)) {
  1371. memset(ZCG(mem), 0, memory_used);
  1372. }
  1373. #endif
  1374. if (!ZCG(mem)) {
  1375. zend_shared_alloc_destroy_xlat_table();
  1376. zend_accel_schedule_restart_if_necessary(ACCEL_RESTART_OOM);
  1377. zend_shared_alloc_unlock();
  1378. if (ZCG(accel_directives).file_cache) {
  1379. new_persistent_script = store_script_in_file_cache(new_persistent_script);
  1380. *from_shared_memory = 1;
  1381. }
  1382. return new_persistent_script;
  1383. }
  1384. zend_shared_alloc_clear_xlat_table();
  1385. /* Copy into shared memory */
  1386. new_persistent_script = zend_accel_script_persist(new_persistent_script, 1);
  1387. zend_shared_alloc_destroy_xlat_table();
  1388. new_persistent_script->is_phar = is_phar_file(new_persistent_script->script.filename);
  1389. /* Consistency check */
  1390. if ((char*)new_persistent_script->mem + new_persistent_script->size != (char*)ZCG(mem)) {
  1391. zend_accel_error(
  1392. ((char*)new_persistent_script->mem + new_persistent_script->size < (char*)ZCG(mem)) ? ACCEL_LOG_ERROR : ACCEL_LOG_WARNING,
  1393. "Internal error: wrong size calculation: %s start=" ZEND_ADDR_FMT ", end=" ZEND_ADDR_FMT ", real=" ZEND_ADDR_FMT "\n",
  1394. ZSTR_VAL(new_persistent_script->script.filename),
  1395. (size_t)new_persistent_script->mem,
  1396. (size_t)((char *)new_persistent_script->mem + new_persistent_script->size),
  1397. (size_t)ZCG(mem));
  1398. }
  1399. new_persistent_script->dynamic_members.checksum = zend_accel_script_checksum(new_persistent_script);
  1400. /* store script structure in the hash table */
  1401. bucket = zend_accel_hash_update(&ZCSG(hash), new_persistent_script->script.filename, 0, new_persistent_script);
  1402. if (bucket) {
  1403. zend_accel_error(ACCEL_LOG_INFO, "Cached script '%s'", ZSTR_VAL(new_persistent_script->script.filename));
  1404. if (key &&
  1405. /* key may contain non-persistent PHAR aliases (see issues #115 and #149) */
  1406. memcmp(ZSTR_VAL(key), "phar://", sizeof("phar://") - 1) != 0 &&
  1407. !zend_string_equals(new_persistent_script->script.filename, key)) {
  1408. /* link key to the same persistent script in hash table */
  1409. zend_string *new_key = accel_new_interned_key(key);
  1410. if (new_key) {
  1411. if (zend_accel_hash_update(&ZCSG(hash), new_key, 1, bucket)) {
  1412. zend_accel_error(ACCEL_LOG_INFO, "Added key '%s'", ZSTR_VAL(key));
  1413. } else {
  1414. zend_accel_error(ACCEL_LOG_DEBUG, "No more entries in hash table!");
  1415. ZSMMG(memory_exhausted) = 1;
  1416. zend_accel_schedule_restart_if_necessary(ACCEL_RESTART_HASH);
  1417. }
  1418. } else {
  1419. zend_accel_schedule_restart_if_necessary(ACCEL_RESTART_OOM);
  1420. }
  1421. }
  1422. }
  1423. new_persistent_script->dynamic_members.memory_consumption = ZEND_ALIGNED_SIZE(new_persistent_script->size);
  1424. zend_shared_alloc_unlock();
  1425. if (ZCG(accel_directives).file_cache) {
  1426. SHM_PROTECT();
  1427. zend_file_cache_script_store(new_persistent_script, 1);
  1428. SHM_UNPROTECT();
  1429. }
  1430. *from_shared_memory = 1;
  1431. return new_persistent_script;
  1432. }
  1433. #define ZEND_AUTOGLOBAL_MASK_SERVER (1 << 0)
  1434. #define ZEND_AUTOGLOBAL_MASK_ENV (1 << 1)
  1435. #define ZEND_AUTOGLOBAL_MASK_REQUEST (1 << 2)
  1436. static int zend_accel_get_auto_globals(void)
  1437. {
  1438. int mask = 0;
  1439. if (zend_hash_exists(&EG(symbol_table), ZSTR_KNOWN(ZEND_STR_AUTOGLOBAL_SERVER))) {
  1440. mask |= ZEND_AUTOGLOBAL_MASK_SERVER;
  1441. }
  1442. if (zend_hash_exists(&EG(symbol_table), ZSTR_KNOWN(ZEND_STR_AUTOGLOBAL_ENV))) {
  1443. mask |= ZEND_AUTOGLOBAL_MASK_ENV;
  1444. }
  1445. if (zend_hash_exists(&EG(symbol_table), ZSTR_KNOWN(ZEND_STR_AUTOGLOBAL_REQUEST))) {
  1446. mask |= ZEND_AUTOGLOBAL_MASK_REQUEST;
  1447. }
  1448. return mask;
  1449. }
  1450. static void zend_accel_set_auto_globals(int mask)
  1451. {
  1452. if (mask & ZEND_AUTOGLOBAL_MASK_SERVER) {
  1453. zend_is_auto_global(ZSTR_KNOWN(ZEND_STR_AUTOGLOBAL_SERVER));
  1454. }
  1455. if (mask & ZEND_AUTOGLOBAL_MASK_ENV) {
  1456. zend_is_auto_global(ZSTR_KNOWN(ZEND_STR_AUTOGLOBAL_ENV));
  1457. }
  1458. if (mask & ZEND_AUTOGLOBAL_MASK_REQUEST) {
  1459. zend_is_auto_global(ZSTR_KNOWN(ZEND_STR_AUTOGLOBAL_REQUEST));
  1460. }
  1461. ZCG(auto_globals_mask) |= mask;
  1462. }
  1463. static void replay_warnings(uint32_t num_warnings, zend_error_info **warnings) {
  1464. for (uint32_t i = 0; i < num_warnings; i++) {
  1465. zend_error_info *warning = warnings[i];
  1466. zend_error_zstr_at(warning->type, warning->filename, warning->lineno, warning->message);
  1467. }
  1468. }
  1469. static zend_persistent_script *opcache_compile_file(zend_file_handle *file_handle, int type, zend_op_array **op_array_p)
  1470. {
  1471. zend_persistent_script *new_persistent_script;
  1472. uint32_t orig_functions_count, orig_class_count;
  1473. zend_op_array *orig_active_op_array;
  1474. zval orig_user_error_handler;
  1475. zend_op_array *op_array;
  1476. int do_bailout = 0;
  1477. accel_time_t timestamp = 0;
  1478. uint32_t orig_compiler_options = 0;
  1479. /* Try to open file */
  1480. if (file_handle->type == ZEND_HANDLE_FILENAME) {
  1481. if (accelerator_orig_zend_stream_open_function(file_handle) != SUCCESS) {
  1482. *op_array_p = NULL;
  1483. if (!EG(exception)) {
  1484. if (type == ZEND_REQUIRE) {
  1485. zend_message_dispatcher(ZMSG_FAILED_REQUIRE_FOPEN, ZSTR_VAL(file_handle->filename));
  1486. } else {
  1487. zend_message_dispatcher(ZMSG_FAILED_INCLUDE_FOPEN, ZSTR_VAL(file_handle->filename));
  1488. }
  1489. }
  1490. return NULL;
  1491. }
  1492. }
  1493. /* check blacklist right after ensuring that file was opened */
  1494. if (file_handle->opened_path && zend_accel_blacklist_is_blacklisted(&accel_blacklist, ZSTR_VAL(file_handle->opened_path), ZSTR_LEN(file_handle->opened_path))) {
  1495. SHM_UNPROTECT();
  1496. ZCSG(blacklist_misses)++;
  1497. SHM_PROTECT();
  1498. *op_array_p = accelerator_orig_compile_file(file_handle, type);
  1499. return NULL;
  1500. }
  1501. if (ZCG(accel_directives).validate_timestamps ||
  1502. ZCG(accel_directives).file_update_protection ||
  1503. ZCG(accel_directives).max_file_size > 0) {
  1504. size_t size = 0;
  1505. /* Obtain the file timestamps, *before* actually compiling them,
  1506. * otherwise we have a race-condition.
  1507. */
  1508. timestamp = zend_get_file_handle_timestamp(file_handle, ZCG(accel_directives).max_file_size > 0 ? &size : NULL);
  1509. /* If we can't obtain a timestamp (that means file is possibly socket)
  1510. * we won't cache it
  1511. */
  1512. if (timestamp == 0) {
  1513. *op_array_p = accelerator_orig_compile_file(file_handle, type);
  1514. return NULL;
  1515. }
  1516. /* check if file is too new (may be it's not written completely yet) */
  1517. if (ZCG(accel_directives).file_update_protection &&
  1518. ((accel_time_t)(ZCG(request_time) - ZCG(accel_directives).file_update_protection) < timestamp)) {
  1519. *op_array_p = accelerator_orig_compile_file(file_handle, type);
  1520. return NULL;
  1521. }
  1522. if (ZCG(accel_directives).max_file_size > 0 && size > (size_t)ZCG(accel_directives).max_file_size) {
  1523. SHM_UNPROTECT();
  1524. ZCSG(blacklist_misses)++;
  1525. SHM_PROTECT();
  1526. *op_array_p = accelerator_orig_compile_file(file_handle, type);
  1527. return NULL;
  1528. }
  1529. }
  1530. /* Save the original values for the op_array, function table and class table */
  1531. orig_active_op_array = CG(active_op_array);
  1532. orig_functions_count = EG(function_table)->nNumUsed;
  1533. orig_class_count = EG(class_table)->nNumUsed;
  1534. ZVAL_COPY_VALUE(&orig_user_error_handler, &EG(user_error_handler));
  1535. /* Override them with ours */
  1536. ZVAL_UNDEF(&EG(user_error_handler));
  1537. if (ZCG(accel_directives).record_warnings) {
  1538. zend_begin_record_errors();
  1539. }
  1540. zend_try {
  1541. orig_compiler_options = CG(compiler_options);
  1542. CG(compiler_options) |= ZEND_COMPILE_HANDLE_OP_ARRAY;
  1543. CG(compiler_options) |= ZEND_COMPILE_IGNORE_INTERNAL_CLASSES;
  1544. CG(compiler_options) |= ZEND_COMPILE_DELAYED_BINDING;
  1545. CG(compiler_options) |= ZEND_COMPILE_NO_CONSTANT_SUBSTITUTION;
  1546. CG(compiler_options) |= ZEND_COMPILE_IGNORE_OTHER_FILES;
  1547. if (ZCG(accel_directives).file_cache) {
  1548. CG(compiler_options) |= ZEND_COMPILE_WITH_FILE_CACHE;
  1549. }
  1550. op_array = *op_array_p = accelerator_orig_compile_file(file_handle, type);
  1551. CG(compiler_options) = orig_compiler_options;
  1552. } zend_catch {
  1553. op_array = NULL;
  1554. do_bailout = 1;
  1555. CG(compiler_options) = orig_compiler_options;
  1556. } zend_end_try();
  1557. /* Restore originals */
  1558. CG(active_op_array) = orig_active_op_array;
  1559. EG(user_error_handler) = orig_user_error_handler;
  1560. EG(record_errors) = 0;
  1561. if (!op_array) {
  1562. /* compilation failed */
  1563. zend_free_recorded_errors();
  1564. if (do_bailout) {
  1565. zend_bailout();
  1566. }
  1567. return NULL;
  1568. }
  1569. /* Build the persistent_script structure.
  1570. Here we aren't sure we would store it, but we will need it
  1571. further anyway.
  1572. */
  1573. new_persistent_script = create_persistent_script();
  1574. new_persistent_script->script.main_op_array = *op_array;
  1575. zend_accel_move_user_functions(CG(function_table), CG(function_table)->nNumUsed - orig_functions_count, &new_persistent_script->script);
  1576. zend_accel_move_user_classes(CG(class_table), CG(class_table)->nNumUsed - orig_class_count, &new_persistent_script->script);
  1577. new_persistent_script->script.first_early_binding_opline =
  1578. (op_array->fn_flags & ZEND_ACC_EARLY_BINDING) ?
  1579. zend_build_delayed_early_binding_list(op_array) :
  1580. (uint32_t)-1;
  1581. new_persistent_script->num_warnings = EG(num_errors);
  1582. new_persistent_script->warnings = EG(errors);
  1583. EG(num_errors) = 0;
  1584. EG(errors) = NULL;
  1585. efree(op_array); /* we have valid persistent_script, so it's safe to free op_array */
  1586. /* Fill in the ping_auto_globals_mask for the new script. If jit for auto globals is enabled we
  1587. will have to ping the used auto global variables before execution */
  1588. if (PG(auto_globals_jit)) {
  1589. new_persistent_script->ping_auto_globals_mask = zend_accel_get_auto_globals();
  1590. }
  1591. if (ZCG(accel_directives).validate_timestamps) {
  1592. /* Obtain the file timestamps, *before* actually compiling them,
  1593. * otherwise we have a race-condition.
  1594. */
  1595. new_persistent_script->timestamp = timestamp;
  1596. new_persistent_script->dynamic_members.revalidate = ZCG(request_time) + ZCG(accel_directives).revalidate_freq;
  1597. }
  1598. if (file_handle->opened_path) {
  1599. new_persistent_script->script.filename = zend_string_copy(file_handle->opened_path);
  1600. } else {
  1601. new_persistent_script->script.filename = zend_string_copy(file_handle->filename);
  1602. }
  1603. zend_string_hash_val(new_persistent_script->script.filename);
  1604. /* Now persistent_script structure is ready in process memory */
  1605. return new_persistent_script;
  1606. }
  1607. zend_op_array *file_cache_compile_file(zend_file_handle *file_handle, int type)
  1608. {
  1609. zend_persistent_script *persistent_script;
  1610. zend_op_array *op_array = NULL;
  1611. int from_memory; /* if the script we've got is stored in SHM */
  1612. if (is_stream_path(ZSTR_VAL(file_handle->filename)) &&
  1613. !is_cacheable_stream_path(ZSTR_VAL(file_handle->filename))) {
  1614. return accelerator_orig_compile_file(file_handle, type);
  1615. }
  1616. if (!file_handle->opened_path) {
  1617. if (file_handle->type == ZEND_HANDLE_FILENAME &&
  1618. accelerator_orig_zend_stream_open_function(file_handle) == FAILURE) {
  1619. if (!EG(exception)) {
  1620. if (type == ZEND_REQUIRE) {
  1621. zend_message_dispatcher(ZMSG_FAILED_REQUIRE_FOPEN, ZSTR_VAL(file_handle->filename));
  1622. } else {
  1623. zend_message_dispatcher(ZMSG_FAILED_INCLUDE_FOPEN, ZSTR_VAL(file_handle->filename));
  1624. }
  1625. }
  1626. return NULL;
  1627. }
  1628. }
  1629. HANDLE_BLOCK_INTERRUPTIONS();
  1630. SHM_UNPROTECT();
  1631. persistent_script = zend_file_cache_script_load(file_handle);
  1632. SHM_PROTECT();
  1633. HANDLE_UNBLOCK_INTERRUPTIONS();
  1634. if (persistent_script) {
  1635. /* see bug #15471 (old BTS) */
  1636. if (persistent_script->script.filename) {
  1637. if (!EG(current_execute_data) || !EG(current_execute_data)->opline ||
  1638. !EG(current_execute_data)->func ||
  1639. !ZEND_USER_CODE(EG(current_execute_data)->func->common.type) ||
  1640. EG(current_execute_data)->opline->opcode != ZEND_INCLUDE_OR_EVAL ||
  1641. (EG(current_execute_data)->opline->extended_value != ZEND_INCLUDE_ONCE &&
  1642. EG(current_execute_data)->opline->extended_value != ZEND_REQUIRE_ONCE)) {
  1643. if (zend_hash_add_empty_element(&EG(included_files), persistent_script->script.filename) != NULL) {
  1644. /* ext/phar has to load phar's metadata into memory */
  1645. if (persistent_script->is_phar) {
  1646. php_stream_statbuf ssb;
  1647. char *fname = emalloc(sizeof("phar://") + ZSTR_LEN(persistent_script->script.filename));
  1648. memcpy(fname, "phar://", sizeof("phar://") - 1);
  1649. memcpy(fname + sizeof("phar://") - 1, ZSTR_VAL(persistent_script->script.filename), ZSTR_LEN(persistent_script->script.filename) + 1);
  1650. php_stream_stat_path(fname, &ssb);
  1651. efree(fname);
  1652. }
  1653. }
  1654. }
  1655. }
  1656. replay_warnings(persistent_script->num_warnings, persistent_script->warnings);
  1657. if (persistent_script->ping_auto_globals_mask & ~ZCG(auto_globals_mask)) {
  1658. zend_accel_set_auto_globals(persistent_script->ping_auto_globals_mask & ~ZCG(auto_globals_mask));
  1659. }
  1660. return zend_accel_load_script(persistent_script, 1);
  1661. }
  1662. persistent_script = opcache_compile_file(file_handle, type, &op_array);
  1663. if (persistent_script) {
  1664. from_memory = 0;
  1665. persistent_script = cache_script_in_file_cache(persistent_script, &from_memory);
  1666. return zend_accel_load_script(persistent_script, from_memory);
  1667. }
  1668. return op_array;
  1669. }
  1670. int check_persistent_script_access(zend_persistent_script *persistent_script)
  1671. {
  1672. char *phar_path, *ptr;
  1673. int ret;
  1674. if ((ZSTR_LEN(persistent_script->script.filename)<sizeof("phar://.phar")) ||
  1675. memcmp(ZSTR_VAL(persistent_script->script.filename), "phar://", sizeof("phar://")-1)) {
  1676. return access(ZSTR_VAL(persistent_script->script.filename), R_OK) != 0;
  1677. } else {
  1678. /* we got a cached file from .phar, so we have to strip prefix and path inside .phar to check access() */
  1679. phar_path = estrdup(ZSTR_VAL(persistent_script->script.filename)+sizeof("phar://")-1);
  1680. if ((ptr = strstr(phar_path, ".phar/")) != NULL)
  1681. {
  1682. *(ptr+sizeof(".phar/")-2) = 0; /* strip path inside .phar file */
  1683. }
  1684. ret = access(phar_path, R_OK) != 0;
  1685. efree(phar_path);
  1686. return ret;
  1687. }
  1688. }
  1689. /* zend_compile() replacement */
  1690. zend_op_array *persistent_compile_file(zend_file_handle *file_handle, int type)
  1691. {
  1692. zend_persistent_script *persistent_script = NULL;
  1693. zend_string *key = NULL;
  1694. int from_shared_memory; /* if the script we've got is stored in SHM */
  1695. if (!file_handle->filename || !ZCG(accelerator_enabled)) {
  1696. /* The Accelerator is disabled, act as if without the Accelerator */
  1697. ZCG(cache_opline) = NULL;
  1698. ZCG(cache_persistent_script) = NULL;
  1699. if (file_handle->filename
  1700. && ZCG(accel_directives).file_cache
  1701. && ZCG(enabled) && accel_startup_ok) {
  1702. return file_cache_compile_file(file_handle, type);
  1703. }
  1704. return accelerator_orig_compile_file(file_handle, type);
  1705. } else if (file_cache_only) {
  1706. ZCG(cache_opline) = NULL;
  1707. ZCG(cache_persistent_script) = NULL;
  1708. return file_cache_compile_file(file_handle, type);
  1709. } else if (!ZCG(accelerator_enabled) ||
  1710. (ZCSG(restart_in_progress) && accel_restart_is_active())) {
  1711. if (ZCG(accel_directives).file_cache) {
  1712. return file_cache_compile_file(file_handle, type);
  1713. }
  1714. ZCG(cache_opline) = NULL;
  1715. ZCG(cache_persistent_script) = NULL;
  1716. return accelerator_orig_compile_file(file_handle, type);
  1717. }
  1718. /* In case this callback is called from include_once, require_once or it's
  1719. * a main FastCGI request, the key must be already calculated, and cached
  1720. * persistent script already found */
  1721. if (ZCG(cache_persistent_script) &&
  1722. ((!EG(current_execute_data) &&
  1723. file_handle->primary_script &&
  1724. ZCG(cache_opline) == NULL) ||
  1725. (EG(current_execute_data) &&
  1726. EG(current_execute_data)->func &&
  1727. ZEND_USER_CODE(EG(current_execute_data)->func->common.type) &&
  1728. ZCG(cache_opline) == EG(current_execute_data)->opline))) {
  1729. persistent_script = ZCG(cache_persistent_script);
  1730. if (ZSTR_LEN(&ZCG(key))) {
  1731. key = &ZCG(key);
  1732. }
  1733. } else {
  1734. if (!ZCG(accel_directives).revalidate_path) {
  1735. /* try to find cached script by key */
  1736. key = accel_make_persistent_key(file_handle->filename);
  1737. if (!key) {
  1738. ZCG(cache_opline) = NULL;
  1739. ZCG(cache_persistent_script) = NULL;
  1740. return accelerator_orig_compile_file(file_handle, type);
  1741. }
  1742. persistent_script = zend_accel_hash_find(&ZCSG(hash), key);
  1743. } else if (UNEXPECTED(is_stream_path(ZSTR_VAL(file_handle->filename)) && !is_cacheable_stream_path(ZSTR_VAL(file_handle->filename)))) {
  1744. ZCG(cache_opline) = NULL;
  1745. ZCG(cache_persistent_script) = NULL;
  1746. return accelerator_orig_compile_file(file_handle, type);
  1747. }
  1748. if (!persistent_script) {
  1749. /* try to find cached script by full real path */
  1750. zend_accel_hash_entry *bucket;
  1751. /* open file to resolve the path */
  1752. if (file_handle->type == ZEND_HANDLE_FILENAME
  1753. && accelerator_orig_zend_stream_open_function(file_handle) == FAILURE) {
  1754. if (!EG(exception)) {
  1755. if (type == ZEND_REQUIRE) {
  1756. zend_message_dispatcher(ZMSG_FAILED_REQUIRE_FOPEN, ZSTR_VAL(file_handle->filename));
  1757. } else {
  1758. zend_message_dispatcher(ZMSG_FAILED_INCLUDE_FOPEN, ZSTR_VAL(file_handle->filename));
  1759. }
  1760. }
  1761. return NULL;
  1762. }
  1763. if (file_handle->opened_path) {
  1764. bucket = zend_accel_hash_find_entry(&ZCSG(hash), file_handle->opened_path);
  1765. if (bucket) {
  1766. persistent_script = (zend_persistent_script *)bucket->data;
  1767. if (key && !persistent_script->corrupted) {
  1768. HANDLE_BLOCK_INTERRUPTIONS();
  1769. SHM_UNPROTECT();
  1770. zend_shared_alloc_lock();
  1771. zend_accel_add_key(key, bucket);
  1772. zend_shared_alloc_unlock();
  1773. SHM_PROTECT();
  1774. HANDLE_UNBLOCK_INTERRUPTIONS();
  1775. }
  1776. }
  1777. }
  1778. }
  1779. }
  1780. /* clear cache */
  1781. ZCG(cache_opline) = NULL;
  1782. ZCG(cache_persistent_script) = NULL;
  1783. if (persistent_script && persistent_script->corrupted) {
  1784. persistent_script = NULL;
  1785. }
  1786. /* Make sure we only increase the currently running processes semaphore
  1787. * once each execution (this function can be called more than once on
  1788. * each execution)
  1789. */
  1790. if (!ZCG(counted)) {
  1791. if (accel_activate_add() == FAILURE) {
  1792. if (ZCG(accel_directives).file_cache) {
  1793. return file_cache_compile_file(file_handle, type);
  1794. }
  1795. return accelerator_orig_compile_file(file_handle, type);
  1796. }
  1797. ZCG(counted) = 1;
  1798. }
  1799. /* Revalidate accessibility of cached file */
  1800. if (EXPECTED(persistent_script != NULL) &&
  1801. UNEXPECTED(ZCG(accel_directives).validate_permission) &&
  1802. file_handle->type == ZEND_HANDLE_FILENAME &&
  1803. UNEXPECTED(check_persistent_script_access(persistent_script))) {
  1804. if (!EG(exception)) {
  1805. if (type == ZEND_REQUIRE) {
  1806. zend_message_dispatcher(ZMSG_FAILED_REQUIRE_FOPEN, ZSTR_VAL(file_handle->filename));
  1807. } else {
  1808. zend_message_dispatcher(ZMSG_FAILED_INCLUDE_FOPEN, ZSTR_VAL(file_handle->filename));
  1809. }
  1810. }
  1811. return NULL;
  1812. }
  1813. HANDLE_BLOCK_INTERRUPTIONS();
  1814. SHM_UNPROTECT();
  1815. /* If script is found then validate_timestamps if option is enabled */
  1816. if (persistent_script && ZCG(accel_directives).validate_timestamps) {
  1817. if (validate_timestamp_and_record(persistent_script, file_handle) == FAILURE) {
  1818. zend_shared_alloc_lock();
  1819. if (!persistent_script->corrupted) {
  1820. persistent_script->corrupted = 1;
  1821. persistent_script->timestamp = 0;
  1822. ZSMMG(wasted_shared_memory) += persistent_script->dynamic_members.memory_consumption;
  1823. if (ZSMMG(memory_exhausted)) {
  1824. zend_accel_restart_reason reason =
  1825. zend_accel_hash_is_full(&ZCSG(hash)) ? ACCEL_RESTART_HASH : ACCEL_RESTART_OOM;
  1826. zend_accel_schedule_restart_if_necessary(reason);
  1827. }
  1828. }
  1829. zend_shared_alloc_unlock();
  1830. persistent_script = NULL;
  1831. }
  1832. }
  1833. /* if turned on - check the compiled script ADLER32 checksum */
  1834. if (persistent_script && ZCG(accel_directives).consistency_checks
  1835. && persistent_script->dynamic_members.hits % ZCG(accel_directives).consistency_checks == 0) {
  1836. unsigned int checksum = zend_accel_script_checksum(persistent_script);
  1837. if (checksum != persistent_script->dynamic_members.checksum ) {
  1838. /* The checksum is wrong */
  1839. zend_accel_error(ACCEL_LOG_INFO, "Checksum failed for '%s': expected=0x%08x, found=0x%08x",
  1840. ZSTR_VAL(persistent_script->script.filename), persistent_script->dynamic_members.checksum, checksum);
  1841. zend_shared_alloc_lock();
  1842. if (!persistent_script->corrupted) {
  1843. persistent_script->corrupted = 1;
  1844. persistent_script->timestamp = 0;
  1845. ZSMMG(wasted_shared_memory) += persistent_script->dynamic_members.memory_consumption;
  1846. if (ZSMMG(memory_exhausted)) {
  1847. zend_accel_restart_reason reason =
  1848. zend_accel_hash_is_full(&ZCSG(hash)) ? ACCEL_RESTART_HASH : ACCEL_RESTART_OOM;
  1849. zend_accel_schedule_restart_if_necessary(reason);
  1850. }
  1851. }
  1852. zend_shared_alloc_unlock();
  1853. persistent_script = NULL;
  1854. }
  1855. }
  1856. /* Check the second level cache */
  1857. if (!persistent_script && ZCG(accel_directives).file_cache) {
  1858. persistent_script = zend_file_cache_script_load(file_handle);
  1859. }
  1860. /* If script was not found or invalidated by validate_timestamps */
  1861. if (!persistent_script) {
  1862. uint32_t old_const_num = zend_hash_next_free_element(EG(zend_constants));
  1863. zend_op_array *op_array;
  1864. /* Cache miss.. */
  1865. ZCSG(misses)++;
  1866. /* No memory left. Behave like without the Accelerator */
  1867. if (ZSMMG(memory_exhausted) || ZCSG(restart_pending)) {
  1868. SHM_PROTECT();
  1869. HANDLE_UNBLOCK_INTERRUPTIONS();
  1870. if (ZCG(accel_directives).file_cache) {
  1871. return file_cache_compile_file(file_handle, type);
  1872. }
  1873. return accelerator_orig_compile_file(file_handle, type);
  1874. }
  1875. SHM_PROTECT();
  1876. HANDLE_UNBLOCK_INTERRUPTIONS();
  1877. persistent_script = opcache_compile_file(file_handle, type, &op_array);
  1878. HANDLE_BLOCK_INTERRUPTIONS();
  1879. SHM_UNPROTECT();
  1880. /* Try and cache the script and assume that it is returned from_shared_memory.
  1881. * If it isn't compile_and_cache_file() changes the flag to 0
  1882. */
  1883. from_shared_memory = 0;
  1884. if (persistent_script) {
  1885. persistent_script = cache_script_in_shared_memory(persistent_script, key, &from_shared_memory);
  1886. }
  1887. /* Caching is disabled, returning op_array;
  1888. * or something went wrong during compilation, returning NULL
  1889. */
  1890. if (!persistent_script) {
  1891. SHM_PROTECT();
  1892. HANDLE_UNBLOCK_INTERRUPTIONS();
  1893. return op_array;
  1894. }
  1895. if (from_shared_memory) {
  1896. /* Delete immutable arrays moved into SHM */
  1897. uint32_t new_const_num = zend_hash_next_free_element(EG(zend_constants));
  1898. while (new_const_num > old_const_num) {
  1899. new_const_num--;
  1900. zend_hash_index_del(EG(zend_constants), new_const_num);
  1901. }
  1902. }
  1903. persistent_script->dynamic_members.last_used = ZCG(request_time);
  1904. SHM_PROTECT();
  1905. HANDLE_UNBLOCK_INTERRUPTIONS();
  1906. } else {
  1907. #if !ZEND_WIN32
  1908. ZCSG(hits)++; /* TBFixed: may lose one hit */
  1909. persistent_script->dynamic_members.hits++; /* see above */
  1910. #else
  1911. #ifdef _M_X64
  1912. InterlockedIncrement64(&ZCSG(hits));
  1913. #else
  1914. InterlockedIncrement(&ZCSG(hits));
  1915. #endif
  1916. InterlockedIncrement64(&persistent_script->dynamic_members.hits);
  1917. #endif
  1918. /* see bug #15471 (old BTS) */
  1919. if (persistent_script->script.filename) {
  1920. if (!EG(current_execute_data) ||
  1921. !EG(current_execute_data)->func ||
  1922. !ZEND_USER_CODE(EG(current_execute_data)->func->common.type) ||
  1923. !EG(current_execute_data)->opline ||
  1924. EG(current_execute_data)->opline->opcode != ZEND_INCLUDE_OR_EVAL ||
  1925. (EG(current_execute_data)->opline->extended_value != ZEND_INCLUDE_ONCE &&
  1926. EG(current_execute_data)->opline->extended_value != ZEND_REQUIRE_ONCE)) {
  1927. if (zend_hash_add_empty_element(&EG(included_files), persistent_script->script.filename) != NULL) {
  1928. /* ext/phar has to load phar's metadata into memory */
  1929. if (persistent_script->is_phar) {
  1930. php_stream_statbuf ssb;
  1931. char *fname = emalloc(sizeof("phar://") + ZSTR_LEN(persistent_script->script.filename));
  1932. memcpy(fname, "phar://", sizeof("phar://") - 1);
  1933. memcpy(fname + sizeof("phar://") - 1, ZSTR_VAL(persistent_script->script.filename), ZSTR_LEN(persistent_script->script.filename) + 1);
  1934. php_stream_stat_path(fname, &ssb);
  1935. efree(fname);
  1936. }
  1937. }
  1938. }
  1939. }
  1940. persistent_script->dynamic_members.last_used = ZCG(request_time);
  1941. SHM_PROTECT();
  1942. HANDLE_UNBLOCK_INTERRUPTIONS();
  1943. replay_warnings(persistent_script->num_warnings, persistent_script->warnings);
  1944. from_shared_memory = 1;
  1945. }
  1946. /* Fetch jit auto globals used in the script before execution */
  1947. if (persistent_script->ping_auto_globals_mask & ~ZCG(auto_globals_mask)) {
  1948. zend_accel_set_auto_globals(persistent_script->ping_auto_globals_mask & ~ZCG(auto_globals_mask));
  1949. }
  1950. return zend_accel_load_script(persistent_script, from_shared_memory);
  1951. }
  1952. static zend_always_inline zend_inheritance_cache_entry* zend_accel_inheritance_cache_find(zend_inheritance_cache_entry *entry, zend_class_entry *ce, zend_class_entry *parent, zend_class_entry **traits_and_interfaces, bool *needs_autoload_ptr)
  1953. {
  1954. uint32_t i;
  1955. ZEND_ASSERT(ce->ce_flags & ZEND_ACC_IMMUTABLE);
  1956. ZEND_ASSERT(!(ce->ce_flags & ZEND_ACC_LINKED));
  1957. while (entry) {
  1958. bool found = 1;
  1959. bool needs_autoload = 0;
  1960. if (entry->parent != parent) {
  1961. found = 0;
  1962. } else {
  1963. for (i = 0; i < ce->num_traits + ce->num_interfaces; i++) {
  1964. if (entry->traits_and_interfaces[i] != traits_and_interfaces[i]) {
  1965. found = 0;
  1966. break;
  1967. }
  1968. }
  1969. if (found && entry->dependencies) {
  1970. for (i = 0; i < entry->dependencies_count; i++) {
  1971. zend_class_entry *ce = zend_lookup_class_ex(entry->dependencies[i].name, NULL, ZEND_FETCH_CLASS_NO_AUTOLOAD);
  1972. if (ce != entry->dependencies[i].ce) {
  1973. if (!ce) {
  1974. needs_autoload = 1;
  1975. } else {
  1976. found = 0;
  1977. break;
  1978. }
  1979. }
  1980. }
  1981. }
  1982. }
  1983. if (found) {
  1984. *needs_autoload_ptr = needs_autoload;
  1985. return entry;
  1986. }
  1987. entry = entry->next;
  1988. }
  1989. return NULL;
  1990. }
  1991. static zend_class_entry* zend_accel_inheritance_cache_get(zend_class_entry *ce, zend_class_entry *parent, zend_class_entry **traits_and_interfaces)
  1992. {
  1993. uint32_t i;
  1994. bool needs_autoload;
  1995. zend_inheritance_cache_entry *entry = ce->inheritance_cache;
  1996. while (entry) {
  1997. entry = zend_accel_inheritance_cache_find(entry, ce, parent, traits_and_interfaces, &needs_autoload);
  1998. if (entry) {
  1999. if (!needs_autoload) {
  2000. replay_warnings(entry->num_warnings, entry->warnings);
  2001. if (ZCSG(map_ptr_last) > CG(map_ptr_last)) {
  2002. zend_map_ptr_extend(ZCSG(map_ptr_last));
  2003. }
  2004. ce = entry->ce;
  2005. if (ZSTR_HAS_CE_CACHE(ce->name)) {
  2006. ZSTR_SET_CE_CACHE_EX(ce->name, ce, 0);
  2007. }
  2008. return ce;
  2009. }
  2010. for (i = 0; i < entry->dependencies_count; i++) {
  2011. zend_class_entry *ce = zend_lookup_class_ex(entry->dependencies[i].name, NULL, 0);
  2012. if (ce == NULL) {
  2013. return NULL;
  2014. }
  2015. }
  2016. }
  2017. }
  2018. return NULL;
  2019. }
  2020. static zend_class_entry* zend_accel_inheritance_cache_add(zend_class_entry *ce, zend_class_entry *proto, zend_class_entry *parent, zend_class_entry **traits_and_interfaces, HashTable *dependencies)
  2021. {
  2022. zend_persistent_script dummy;
  2023. size_t size;
  2024. uint32_t i;
  2025. bool needs_autoload;
  2026. zend_class_entry *new_ce;
  2027. zend_inheritance_cache_entry *entry;
  2028. ZEND_ASSERT(!(ce->ce_flags & ZEND_ACC_IMMUTABLE));
  2029. ZEND_ASSERT(ce->ce_flags & ZEND_ACC_LINKED);
  2030. if (!ZCG(accelerator_enabled) ||
  2031. (ZCSG(restart_in_progress) && accel_restart_is_active())) {
  2032. return NULL;
  2033. }
  2034. if (traits_and_interfaces && dependencies) {
  2035. for (i = 0; i < proto->num_traits + proto->num_interfaces; i++) {
  2036. if (traits_and_interfaces[i]) {
  2037. zend_hash_del(dependencies, traits_and_interfaces[i]->name);
  2038. }
  2039. }
  2040. }
  2041. SHM_UNPROTECT();
  2042. zend_shared_alloc_lock();
  2043. entry = ce->inheritance_cache;
  2044. while (entry) {
  2045. entry = zend_accel_inheritance_cache_find(entry, ce, parent, traits_and_interfaces, &needs_autoload);
  2046. if (entry) {
  2047. if (!needs_autoload) {
  2048. zend_shared_alloc_unlock();
  2049. SHM_PROTECT();
  2050. zend_map_ptr_extend(ZCSG(map_ptr_last));
  2051. return entry->ce;
  2052. }
  2053. ZEND_ASSERT(0); // entry = entry->next; // This shouldn't be posible ???
  2054. }
  2055. }
  2056. zend_shared_alloc_init_xlat_table();
  2057. memset(&dummy, 0, sizeof(dummy));
  2058. dummy.size = ZEND_ALIGNED_SIZE(
  2059. sizeof(zend_inheritance_cache_entry) -
  2060. sizeof(void*) +
  2061. (sizeof(void*) * (proto->num_traits + proto->num_interfaces)));
  2062. if (dependencies) {
  2063. dummy.size += ZEND_ALIGNED_SIZE(zend_hash_num_elements(dependencies) * sizeof(zend_class_dependency));
  2064. }
  2065. ZCG(current_persistent_script) = &dummy;
  2066. zend_persist_class_entry_calc(ce);
  2067. zend_persist_warnings_calc(EG(num_errors), EG(errors));
  2068. size = dummy.size;
  2069. zend_shared_alloc_clear_xlat_table();
  2070. #if ZEND_MM_ALIGNMENT < 8
  2071. /* Align to 8-byte boundary */
  2072. ZCG(mem) = zend_shared_alloc(size + 8);
  2073. #else
  2074. ZCG(mem) = zend_shared_alloc(size);
  2075. #endif
  2076. if (!ZCG(mem)) {
  2077. zend_shared_alloc_destroy_xlat_table();
  2078. zend_shared_alloc_unlock();
  2079. SHM_PROTECT();
  2080. return NULL;
  2081. }
  2082. zend_map_ptr_extend(ZCSG(map_ptr_last));
  2083. #if ZEND_MM_ALIGNMENT < 8
  2084. /* Align to 8-byte boundary */
  2085. ZCG(mem) = (void*)(((zend_uintptr_t)ZCG(mem) + 7L) & ~7L);
  2086. #endif
  2087. memset(ZCG(mem), 0, size);
  2088. entry = (zend_inheritance_cache_entry*)ZCG(mem);
  2089. ZCG(mem) = (char*)ZCG(mem) +
  2090. ZEND_ALIGNED_SIZE(
  2091. (sizeof(zend_inheritance_cache_entry) -
  2092. sizeof(void*) +
  2093. (sizeof(void*) * (proto->num_traits + proto->num_interfaces))));
  2094. entry->parent = parent;
  2095. for (i = 0; i < proto->num_traits + proto->num_interfaces; i++) {
  2096. entry->traits_and_interfaces[i] = traits_and_interfaces[i];
  2097. }
  2098. if (dependencies && zend_hash_num_elements(dependencies)) {
  2099. zend_string *dep_name;
  2100. zend_class_entry *dep_ce;
  2101. i = 0;
  2102. entry->dependencies_count = zend_hash_num_elements(dependencies);
  2103. entry->dependencies = (zend_class_dependency*)ZCG(mem);
  2104. ZEND_HASH_FOREACH_STR_KEY_PTR(dependencies, dep_name, dep_ce) {
  2105. #if ZEND_DEBUG
  2106. ZEND_ASSERT(zend_accel_in_shm(dep_name));
  2107. #endif
  2108. entry->dependencies[i].name = dep_name;
  2109. entry->dependencies[i].ce = dep_ce;
  2110. i++;
  2111. } ZEND_HASH_FOREACH_END();
  2112. ZCG(mem) = (char*)ZCG(mem) + zend_hash_num_elements(dependencies) * sizeof(zend_class_dependency);
  2113. }
  2114. entry->ce = new_ce = zend_persist_class_entry(ce);
  2115. zend_update_parent_ce(new_ce);
  2116. entry->num_warnings = EG(num_errors);
  2117. entry->warnings = zend_persist_warnings(EG(num_errors), EG(errors));
  2118. entry->next = proto->inheritance_cache;
  2119. proto->inheritance_cache = entry;
  2120. EG(num_errors) = 0;
  2121. EG(errors) = NULL;
  2122. ZCSG(map_ptr_last) = CG(map_ptr_last);
  2123. zend_shared_alloc_destroy_xlat_table();
  2124. zend_shared_alloc_unlock();
  2125. SHM_PROTECT();
  2126. /* Consistency check */
  2127. if ((char*)entry + size != (char*)ZCG(mem)) {
  2128. zend_accel_error(
  2129. ((char*)entry + size < (char*)ZCG(mem)) ? ACCEL_LOG_ERROR : ACCEL_LOG_WARNING,
  2130. "Internal error: wrong class size calculation: %s start=" ZEND_ADDR_FMT ", end=" ZEND_ADDR_FMT ", real=" ZEND_ADDR_FMT "\n",
  2131. ZSTR_VAL(ce->name),
  2132. (size_t)entry,
  2133. (size_t)((char *)entry + size),
  2134. (size_t)ZCG(mem));
  2135. }
  2136. zend_map_ptr_extend(ZCSG(map_ptr_last));
  2137. return new_ce;
  2138. }
  2139. #ifdef ZEND_WIN32
  2140. static int accel_gen_uname_id(void)
  2141. {
  2142. PHP_MD5_CTX ctx;
  2143. unsigned char digest[16];
  2144. wchar_t uname[UNLEN + 1];
  2145. DWORD unsize = UNLEN;
  2146. if (!GetUserNameW(uname, &unsize)) {
  2147. return FAILURE;
  2148. }
  2149. PHP_MD5Init(&ctx);
  2150. PHP_MD5Update(&ctx, (void *) uname, (unsize - 1) * sizeof(wchar_t));
  2151. PHP_MD5Update(&ctx, ZCG(accel_directives).cache_id, strlen(ZCG(accel_directives).cache_id));
  2152. PHP_MD5Final(digest, &ctx);
  2153. php_hash_bin2hex(accel_uname_id, digest, sizeof digest);
  2154. return SUCCESS;
  2155. }
  2156. #endif
  2157. /* zend_stream_open_function() replacement for PHP 5.3 and above */
  2158. static zend_result persistent_stream_open_function(zend_file_handle *handle)
  2159. {
  2160. if (ZCG(cache_persistent_script)) {
  2161. /* check if callback is called from include_once or it's a main request */
  2162. if ((!EG(current_execute_data) &&
  2163. handle->primary_script &&
  2164. ZCG(cache_opline) == NULL) ||
  2165. (EG(current_execute_data) &&
  2166. EG(current_execute_data)->func &&
  2167. ZEND_USER_CODE(EG(current_execute_data)->func->common.type) &&
  2168. ZCG(cache_opline) == EG(current_execute_data)->opline)) {
  2169. /* we are in include_once or FastCGI request */
  2170. handle->opened_path = zend_string_copy(ZCG(cache_persistent_script)->script.filename);
  2171. return SUCCESS;
  2172. }
  2173. ZCG(cache_opline) = NULL;
  2174. ZCG(cache_persistent_script) = NULL;
  2175. }
  2176. return accelerator_orig_zend_stream_open_function(handle);
  2177. }
  2178. /* zend_resolve_path() replacement for PHP 5.3 and above */
  2179. static zend_string* persistent_zend_resolve_path(zend_string *filename)
  2180. {
  2181. if (!file_cache_only &&
  2182. ZCG(accelerator_enabled)) {
  2183. /* check if callback is called from include_once or it's a main request */
  2184. if ((!EG(current_execute_data)) ||
  2185. (EG(current_execute_data) &&
  2186. EG(current_execute_data)->func &&
  2187. ZEND_USER_CODE(EG(current_execute_data)->func->common.type) &&
  2188. EG(current_execute_data)->opline->opcode == ZEND_INCLUDE_OR_EVAL &&
  2189. (EG(current_execute_data)->opline->extended_value == ZEND_INCLUDE_ONCE ||
  2190. EG(current_execute_data)->opline->extended_value == ZEND_REQUIRE_ONCE))) {
  2191. /* we are in include_once or FastCGI request */
  2192. zend_string *resolved_path;
  2193. zend_string *key = NULL;
  2194. if (!ZCG(accel_directives).revalidate_path) {
  2195. /* lookup by "not-real" path */
  2196. key = accel_make_persistent_key(filename);
  2197. if (key) {
  2198. zend_accel_hash_entry *bucket = zend_accel_hash_find_entry(&ZCSG(hash), key);
  2199. if (bucket != NULL) {
  2200. zend_persistent_script *persistent_script = (zend_persistent_script *)bucket->data;
  2201. if (!persistent_script->corrupted) {
  2202. ZCG(cache_opline) = EG(current_execute_data) ? EG(current_execute_data)->opline : NULL;
  2203. ZCG(cache_persistent_script) = persistent_script;
  2204. return zend_string_copy(persistent_script->script.filename);
  2205. }
  2206. }
  2207. } else {
  2208. ZCG(cache_opline) = NULL;
  2209. ZCG(cache_persistent_script) = NULL;
  2210. return accelerator_orig_zend_resolve_path(filename);
  2211. }
  2212. }
  2213. /* find the full real path */
  2214. resolved_path = accelerator_orig_zend_resolve_path(filename);
  2215. if (resolved_path) {
  2216. /* lookup by real path */
  2217. zend_accel_hash_entry *bucket = zend_accel_hash_find_entry(&ZCSG(hash), resolved_path);
  2218. if (bucket) {
  2219. zend_persistent_script *persistent_script = (zend_persistent_script *)bucket->data;
  2220. if (!persistent_script->corrupted) {
  2221. if (key) {
  2222. /* add another "key" for the same bucket */
  2223. HANDLE_BLOCK_INTERRUPTIONS();
  2224. SHM_UNPROTECT();
  2225. zend_shared_alloc_lock();
  2226. zend_accel_add_key(key, bucket);
  2227. zend_shared_alloc_unlock();
  2228. SHM_PROTECT();
  2229. HANDLE_UNBLOCK_INTERRUPTIONS();
  2230. } else {
  2231. ZSTR_LEN(&ZCG(key)) = 0;
  2232. }
  2233. ZCG(cache_opline) = EG(current_execute_data) ? EG(current_execute_data)->opline : NULL;
  2234. ZCG(cache_persistent_script) = persistent_script;
  2235. return resolved_path;
  2236. }
  2237. }
  2238. }
  2239. ZCG(cache_opline) = NULL;
  2240. ZCG(cache_persistent_script) = NULL;
  2241. return resolved_path;
  2242. }
  2243. }
  2244. ZCG(cache_opline) = NULL;
  2245. ZCG(cache_persistent_script) = NULL;
  2246. return accelerator_orig_zend_resolve_path(filename);
  2247. }
  2248. static void zend_reset_cache_vars(void)
  2249. {
  2250. ZSMMG(memory_exhausted) = 0;
  2251. ZCSG(hits) = 0;
  2252. ZCSG(misses) = 0;
  2253. ZCSG(blacklist_misses) = 0;
  2254. ZSMMG(wasted_shared_memory) = 0;
  2255. ZCSG(restart_pending) = 0;
  2256. ZCSG(force_restart_time) = 0;
  2257. ZCSG(map_ptr_last) = CG(map_ptr_last);
  2258. }
  2259. static void accel_reset_pcre_cache(void)
  2260. {
  2261. Bucket *p;
  2262. if (PCRE_G(per_request_cache)) {
  2263. return;
  2264. }
  2265. ZEND_HASH_FOREACH_BUCKET(&PCRE_G(pcre_cache), p) {
  2266. /* Remove PCRE cache entries with inconsistent keys */
  2267. if (zend_accel_in_shm(p->key)) {
  2268. p->key = NULL;
  2269. zend_hash_del_bucket(&PCRE_G(pcre_cache), p);
  2270. }
  2271. } ZEND_HASH_FOREACH_END();
  2272. }
  2273. zend_result accel_activate(INIT_FUNC_ARGS)
  2274. {
  2275. if (!ZCG(enabled) || !accel_startup_ok) {
  2276. ZCG(accelerator_enabled) = 0;
  2277. return SUCCESS;
  2278. }
  2279. /* PHP-5.4 and above return "double", but we use 1 sec precision */
  2280. ZCG(auto_globals_mask) = 0;
  2281. ZCG(request_time) = (time_t)sapi_get_request_time();
  2282. ZCG(cache_opline) = NULL;
  2283. ZCG(cache_persistent_script) = NULL;
  2284. ZCG(include_path_key_len) = 0;
  2285. ZCG(include_path_check) = 1;
  2286. ZCG(cwd) = NULL;
  2287. ZCG(cwd_key_len) = 0;
  2288. ZCG(cwd_check) = 1;
  2289. if (file_cache_only) {
  2290. ZCG(accelerator_enabled) = 0;
  2291. return SUCCESS;
  2292. }
  2293. #ifndef ZEND_WIN32
  2294. if (ZCG(accel_directives).validate_root) {
  2295. struct stat buf;
  2296. if (stat("/", &buf) != 0) {
  2297. ZCG(root_hash) = 0;
  2298. } else {
  2299. ZCG(root_hash) = buf.st_ino;
  2300. if (sizeof(buf.st_ino) > sizeof(ZCG(root_hash))) {
  2301. if (ZCG(root_hash) != buf.st_ino) {
  2302. zend_string *key = zend_string_init("opcache.enable", sizeof("opcache.enable")-1, 0);
  2303. zend_alter_ini_entry_chars(key, "0", 1, ZEND_INI_SYSTEM, ZEND_INI_STAGE_RUNTIME);
  2304. zend_string_release_ex(key, 0);
  2305. zend_accel_error(ACCEL_LOG_WARNING, "Can't cache files in chroot() directory with too big inode");
  2306. return SUCCESS;
  2307. }
  2308. }
  2309. }
  2310. } else {
  2311. ZCG(root_hash) = 0;
  2312. }
  2313. #endif
  2314. HANDLE_BLOCK_INTERRUPTIONS();
  2315. SHM_UNPROTECT();
  2316. if (ZCG(counted)) {
  2317. #ifdef ZTS
  2318. zend_accel_error(ACCEL_LOG_WARNING, "Stuck count for thread id %lu", (unsigned long) tsrm_thread_id());
  2319. #else
  2320. zend_accel_error(ACCEL_LOG_WARNING, "Stuck count for pid %d", getpid());
  2321. #endif
  2322. accel_unlock_all();
  2323. ZCG(counted) = 0;
  2324. }
  2325. if (ZCSG(restart_pending)) {
  2326. zend_shared_alloc_lock();
  2327. if (ZCSG(restart_pending) != 0) { /* check again, to ensure that the cache wasn't already cleaned by another process */
  2328. if (accel_is_inactive() == SUCCESS) {
  2329. zend_accel_error(ACCEL_LOG_DEBUG, "Restarting!");
  2330. ZCSG(restart_pending) = 0;
  2331. switch ZCSG(restart_reason) {
  2332. case ACCEL_RESTART_OOM:
  2333. ZCSG(oom_restarts)++;
  2334. break;
  2335. case ACCEL_RESTART_HASH:
  2336. ZCSG(hash_restarts)++;
  2337. break;
  2338. case ACCEL_RESTART_USER:
  2339. ZCSG(manual_restarts)++;
  2340. break;
  2341. }
  2342. accel_restart_enter();
  2343. zend_map_ptr_reset();
  2344. zend_reset_cache_vars();
  2345. zend_accel_hash_clean(&ZCSG(hash));
  2346. if (ZCG(accel_directives).interned_strings_buffer) {
  2347. accel_interned_strings_restore_state();
  2348. }
  2349. zend_shared_alloc_restore_state();
  2350. if (ZCSG(preload_script)) {
  2351. preload_restart();
  2352. }
  2353. #ifdef HAVE_JIT
  2354. zend_jit_restart();
  2355. #endif
  2356. ZCSG(accelerator_enabled) = ZCSG(cache_status_before_restart);
  2357. if (ZCSG(last_restart_time) < ZCG(request_time)) {
  2358. ZCSG(last_restart_time) = ZCG(request_time);
  2359. } else {
  2360. ZCSG(last_restart_time)++;
  2361. }
  2362. accel_restart_leave();
  2363. }
  2364. }
  2365. zend_shared_alloc_unlock();
  2366. }
  2367. ZCG(accelerator_enabled) = ZCSG(accelerator_enabled);
  2368. SHM_PROTECT();
  2369. HANDLE_UNBLOCK_INTERRUPTIONS();
  2370. if (ZCG(accelerator_enabled) && ZCSG(last_restart_time) != ZCG(last_restart_time)) {
  2371. /* SHM was reinitialized. */
  2372. ZCG(last_restart_time) = ZCSG(last_restart_time);
  2373. /* Reset in-process realpath cache */
  2374. realpath_cache_clean();
  2375. accel_reset_pcre_cache();
  2376. ZCG(pcre_reseted) = 0;
  2377. } else if (!ZCG(accelerator_enabled) && !ZCG(pcre_reseted)) {
  2378. accel_reset_pcre_cache();
  2379. ZCG(pcre_reseted) = 1;
  2380. }
  2381. #ifdef HAVE_JIT
  2382. zend_jit_activate();
  2383. #endif
  2384. if (ZCSG(preload_script)) {
  2385. preload_activate();
  2386. }
  2387. return SUCCESS;
  2388. }
  2389. #ifdef HAVE_JIT
  2390. void accel_deactivate(void)
  2391. {
  2392. zend_jit_deactivate();
  2393. }
  2394. #endif
  2395. zend_result accel_post_deactivate(void)
  2396. {
  2397. if (ZCG(cwd)) {
  2398. zend_string_release_ex(ZCG(cwd), 0);
  2399. ZCG(cwd) = NULL;
  2400. }
  2401. if (!ZCG(enabled) || !accel_startup_ok) {
  2402. return SUCCESS;
  2403. }
  2404. zend_shared_alloc_safe_unlock(); /* be sure we didn't leave cache locked */
  2405. accel_unlock_all();
  2406. ZCG(counted) = 0;
  2407. return SUCCESS;
  2408. }
  2409. static int accelerator_remove_cb(zend_extension *element1, zend_extension *element2)
  2410. {
  2411. (void)element2; /* keep the compiler happy */
  2412. if (!strcmp(element1->name, ACCELERATOR_PRODUCT_NAME )) {
  2413. element1->startup = NULL;
  2414. #if 0
  2415. /* We have to call shutdown callback it to free TS resources */
  2416. element1->shutdown = NULL;
  2417. #endif
  2418. element1->activate = NULL;
  2419. element1->deactivate = NULL;
  2420. element1->op_array_handler = NULL;
  2421. #ifdef __DEBUG_MESSAGES__
  2422. fprintf(stderr, ACCELERATOR_PRODUCT_NAME " is disabled: %s\n", (zps_failure_reason ? zps_failure_reason : "unknown error"));
  2423. fflush(stderr);
  2424. #endif
  2425. }
  2426. return 0;
  2427. }
  2428. static void zps_startup_failure(char *reason, char *api_reason, int (*cb)(zend_extension *, zend_extension *))
  2429. {
  2430. accel_startup_ok = 0;
  2431. zps_failure_reason = reason;
  2432. zps_api_failure_reason = api_reason?api_reason:reason;
  2433. zend_llist_del_element(&zend_extensions, NULL, (int (*)(void *, void *))cb);
  2434. }
  2435. static inline int accel_find_sapi(void)
  2436. {
  2437. static const char *supported_sapis[] = {
  2438. "apache",
  2439. "fastcgi",
  2440. "cli-server",
  2441. "cgi-fcgi",
  2442. "fpm-fcgi",
  2443. "fpmi-fcgi",
  2444. "apache2handler",
  2445. "litespeed",
  2446. "uwsgi",
  2447. NULL
  2448. };
  2449. const char **sapi_name;
  2450. if (sapi_module.name) {
  2451. for (sapi_name = supported_sapis; *sapi_name; sapi_name++) {
  2452. if (strcmp(sapi_module.name, *sapi_name) == 0) {
  2453. return SUCCESS;
  2454. }
  2455. }
  2456. if (ZCG(accel_directives).enable_cli && (
  2457. strcmp(sapi_module.name, "cli") == 0
  2458. || strcmp(sapi_module.name, "phpdbg") == 0)) {
  2459. return SUCCESS;
  2460. }
  2461. }
  2462. return FAILURE;
  2463. }
  2464. static int zend_accel_init_shm(void)
  2465. {
  2466. int i;
  2467. zend_shared_alloc_lock();
  2468. if (ZCG(accel_directives).interned_strings_buffer) {
  2469. accel_shared_globals = zend_shared_alloc((ZCG(accel_directives).interned_strings_buffer * 1024 * 1024));
  2470. } else {
  2471. /* Make sure there is always at least one interned string hash slot,
  2472. * so the table can be queried unconditionally. */
  2473. accel_shared_globals = zend_shared_alloc(sizeof(zend_accel_shared_globals) + sizeof(uint32_t));
  2474. }
  2475. if (!accel_shared_globals) {
  2476. zend_accel_error_noreturn(ACCEL_LOG_FATAL, "Insufficient shared memory!");
  2477. zend_shared_alloc_unlock();
  2478. return FAILURE;
  2479. }
  2480. memset(accel_shared_globals, 0, sizeof(zend_accel_shared_globals));
  2481. ZSMMG(app_shared_globals) = accel_shared_globals;
  2482. zend_accel_hash_init(&ZCSG(hash), ZCG(accel_directives).max_accelerated_files);
  2483. if (ZCG(accel_directives).interned_strings_buffer) {
  2484. uint32_t hash_size;
  2485. /* must be a power of two */
  2486. hash_size = ZCG(accel_directives).interned_strings_buffer * (32 * 1024);
  2487. hash_size |= (hash_size >> 1);
  2488. hash_size |= (hash_size >> 2);
  2489. hash_size |= (hash_size >> 4);
  2490. hash_size |= (hash_size >> 8);
  2491. hash_size |= (hash_size >> 16);
  2492. ZCSG(interned_strings).nTableMask = hash_size << 2;
  2493. ZCSG(interned_strings).nNumOfElements = 0;
  2494. ZCSG(interned_strings).start =
  2495. (zend_string*)((char*)&ZCSG(interned_strings) +
  2496. sizeof(zend_string_table) +
  2497. ((hash_size + 1) * sizeof(uint32_t))) +
  2498. 8;
  2499. ZCSG(interned_strings).top =
  2500. ZCSG(interned_strings).start;
  2501. ZCSG(interned_strings).end =
  2502. (zend_string*)((char*)accel_shared_globals +
  2503. ZCG(accel_directives).interned_strings_buffer * 1024 * 1024);
  2504. ZCSG(interned_strings).saved_top = NULL;
  2505. memset((char*)&ZCSG(interned_strings) + sizeof(zend_string_table),
  2506. STRTAB_INVALID_POS,
  2507. (char*)ZCSG(interned_strings).start -
  2508. ((char*)&ZCSG(interned_strings) + sizeof(zend_string_table)));
  2509. } else {
  2510. *STRTAB_HASH_TO_SLOT(&ZCSG(interned_strings), 0) = STRTAB_INVALID_POS;
  2511. }
  2512. /* We can reuse init_interned_string_for_php for the "init_existing_interned" case,
  2513. * because the function does not create new interned strings at runtime. */
  2514. zend_interned_strings_set_request_storage_handlers(
  2515. accel_new_interned_string_for_php,
  2516. accel_init_interned_string_for_php,
  2517. accel_init_interned_string_for_php);
  2518. zend_reset_cache_vars();
  2519. ZCSG(oom_restarts) = 0;
  2520. ZCSG(hash_restarts) = 0;
  2521. ZCSG(manual_restarts) = 0;
  2522. ZCSG(accelerator_enabled) = 1;
  2523. ZCSG(start_time) = zend_accel_get_time();
  2524. ZCSG(last_restart_time) = 0;
  2525. ZCSG(restart_in_progress) = 0;
  2526. for (i = 0; i < -HT_MIN_MASK; i++) {
  2527. ZCSG(uninitialized_bucket)[i] = HT_INVALID_IDX;
  2528. }
  2529. zend_shared_alloc_unlock();
  2530. return SUCCESS;
  2531. }
  2532. static void accel_globals_ctor(zend_accel_globals *accel_globals)
  2533. {
  2534. #if defined(COMPILE_DL_OPCACHE) && defined(ZTS)
  2535. ZEND_TSRMLS_CACHE_UPDATE();
  2536. #endif
  2537. memset(accel_globals, 0, sizeof(zend_accel_globals));
  2538. }
  2539. #ifdef HAVE_HUGE_CODE_PAGES
  2540. # ifndef _WIN32
  2541. # include <sys/mman.h>
  2542. # ifndef MAP_ANON
  2543. # ifdef MAP_ANONYMOUS
  2544. # define MAP_ANON MAP_ANONYMOUS
  2545. # endif
  2546. # endif
  2547. # ifndef MAP_FAILED
  2548. # define MAP_FAILED ((void*)-1)
  2549. # endif
  2550. # ifdef MAP_ALIGNED_SUPER
  2551. # include <sys/types.h>
  2552. # include <sys/sysctl.h>
  2553. # include <sys/user.h>
  2554. # define MAP_HUGETLB MAP_ALIGNED_SUPER
  2555. # endif
  2556. # endif
  2557. # if defined(MAP_HUGETLB) || defined(MADV_HUGEPAGE)
  2558. static int accel_remap_huge_pages(void *start, size_t size, size_t real_size, const char *name, size_t offset)
  2559. {
  2560. void *ret = MAP_FAILED;
  2561. void *mem;
  2562. mem = mmap(NULL, size,
  2563. PROT_READ | PROT_WRITE,
  2564. MAP_PRIVATE | MAP_ANONYMOUS,
  2565. -1, 0);
  2566. if (mem == MAP_FAILED) {
  2567. zend_error(E_WARNING,
  2568. ACCELERATOR_PRODUCT_NAME " huge_code_pages: mmap failed: %s (%d)",
  2569. strerror(errno), errno);
  2570. return -1;
  2571. }
  2572. memcpy(mem, start, real_size);
  2573. # ifdef MAP_HUGETLB
  2574. ret = mmap(start, size,
  2575. PROT_READ | PROT_WRITE | PROT_EXEC,
  2576. MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED | MAP_HUGETLB,
  2577. -1, 0);
  2578. # endif
  2579. if (ret == MAP_FAILED) {
  2580. ret = mmap(start, size,
  2581. PROT_READ | PROT_WRITE | PROT_EXEC,
  2582. MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED,
  2583. -1, 0);
  2584. /* this should never happen? */
  2585. ZEND_ASSERT(ret != MAP_FAILED);
  2586. # ifdef MADV_HUGEPAGE
  2587. if (-1 == madvise(start, size, MADV_HUGEPAGE)) {
  2588. memcpy(start, mem, real_size);
  2589. mprotect(start, size, PROT_READ | PROT_EXEC);
  2590. munmap(mem, size);
  2591. zend_error(E_WARNING,
  2592. ACCELERATOR_PRODUCT_NAME " huge_code_pages: madvise(HUGEPAGE) failed: %s (%d)",
  2593. strerror(errno), errno);
  2594. return -1;
  2595. }
  2596. # else
  2597. memcpy(start, mem, real_size);
  2598. mprotect(start, size, PROT_READ | PROT_EXEC);
  2599. munmap(mem, size);
  2600. zend_error(E_WARNING,
  2601. ACCELERATOR_PRODUCT_NAME " huge_code_pages: mmap(HUGETLB) failed: %s (%d)",
  2602. strerror(errno), errno);
  2603. return -1;
  2604. # endif
  2605. }
  2606. if (ret == start) {
  2607. memcpy(start, mem, real_size);
  2608. mprotect(start, size, PROT_READ | PROT_EXEC);
  2609. }
  2610. munmap(mem, size);
  2611. return (ret == start) ? 0 : -1;
  2612. }
  2613. static void accel_move_code_to_huge_pages(void)
  2614. {
  2615. #if defined(__linux__)
  2616. FILE *f;
  2617. long unsigned int huge_page_size = 2 * 1024 * 1024;
  2618. f = fopen("/proc/self/maps", "r");
  2619. if (f) {
  2620. long unsigned int start, end, offset, inode;
  2621. char perm[5], dev[10], name[MAXPATHLEN];
  2622. int ret;
  2623. while (1) {
  2624. ret = fscanf(f, "%lx-%lx %4s %lx %9s %ld %s\n", &start, &end, perm, &offset, dev, &inode, name);
  2625. if (ret == 7) {
  2626. if (perm[0] == 'r' && perm[1] == '-' && perm[2] == 'x' && name[0] == '/') {
  2627. long unsigned int seg_start = ZEND_MM_ALIGNED_SIZE_EX(start, huge_page_size);
  2628. long unsigned int seg_end = (end & ~(huge_page_size-1L));
  2629. long unsigned int real_end;
  2630. ret = fscanf(f, "%lx-", &start);
  2631. if (ret == 1 && start == seg_end + huge_page_size) {
  2632. real_end = end;
  2633. seg_end = start;
  2634. } else {
  2635. real_end = seg_end;
  2636. }
  2637. if (seg_end > seg_start) {
  2638. zend_accel_error(ACCEL_LOG_DEBUG, "remap to huge page %lx-%lx %s \n", seg_start, seg_end, name);
  2639. accel_remap_huge_pages((void*)seg_start, seg_end - seg_start, real_end - seg_start, name, offset + seg_start - start);
  2640. }
  2641. break;
  2642. }
  2643. } else {
  2644. break;
  2645. }
  2646. }
  2647. fclose(f);
  2648. }
  2649. #elif defined(__FreeBSD__)
  2650. size_t s = 0;
  2651. int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_VMMAP, getpid()};
  2652. long unsigned int huge_page_size = 2 * 1024 * 1024;
  2653. if (sysctl(mib, 4, NULL, &s, NULL, 0) == 0) {
  2654. s = s * 4 / 3;
  2655. void *addr = mmap(NULL, s, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
  2656. if (addr != MAP_FAILED) {
  2657. if (sysctl(mib, 4, addr, &s, NULL, 0) == 0) {
  2658. uintptr_t start = (uintptr_t)addr;
  2659. uintptr_t end = start + s;
  2660. while (start < end) {
  2661. struct kinfo_vmentry *entry = (struct kinfo_vmentry *)start;
  2662. size_t sz = entry->kve_structsize;
  2663. if (sz == 0) {
  2664. break;
  2665. }
  2666. int permflags = entry->kve_protection;
  2667. if ((permflags & KVME_PROT_READ) && !(permflags & KVME_PROT_WRITE) &&
  2668. (permflags & KVME_PROT_EXEC) && entry->kve_path[0] != '\0') {
  2669. long unsigned int seg_start = ZEND_MM_ALIGNED_SIZE_EX(start, huge_page_size);
  2670. long unsigned int seg_end = (end & ~(huge_page_size-1L));
  2671. if (seg_end > seg_start) {
  2672. zend_accel_error(ACCEL_LOG_DEBUG, "remap to huge page %lx-%lx %s \n", seg_start, seg_end, entry->kve_path);
  2673. accel_remap_huge_pages((void*)seg_start, seg_end - seg_start, seg_end - seg_start, entry->kve_path, entry->kve_offset + seg_start - start);
  2674. // First relevant segment found is our binary
  2675. break;
  2676. }
  2677. }
  2678. start += sz;
  2679. }
  2680. }
  2681. munmap(addr, s);
  2682. }
  2683. }
  2684. #endif
  2685. }
  2686. # else
  2687. static void accel_move_code_to_huge_pages(void)
  2688. {
  2689. zend_error(E_WARNING, ACCELERATOR_PRODUCT_NAME ": opcache.huge_code_pages has no affect as huge page is not supported");
  2690. return;
  2691. }
  2692. # endif /* defined(MAP_HUGETLB) || defined(MADV_HUGEPAGE) */
  2693. #endif /* HAVE_HUGE_CODE_PAGES */
  2694. static int accel_startup(zend_extension *extension)
  2695. {
  2696. #ifdef ZTS
  2697. accel_globals_id = ts_allocate_id(&accel_globals_id, sizeof(zend_accel_globals), (ts_allocate_ctor) accel_globals_ctor, NULL);
  2698. #else
  2699. accel_globals_ctor(&accel_globals);
  2700. #endif
  2701. #ifdef HAVE_JIT
  2702. zend_jit_init();
  2703. #endif
  2704. #ifdef ZEND_WIN32
  2705. # if !defined(__has_feature) || !__has_feature(address_sanitizer)
  2706. _setmaxstdio(2048); /* The default configuration is limited to 512 stdio files */
  2707. # endif
  2708. #endif
  2709. if (start_accel_module() == FAILURE) {
  2710. accel_startup_ok = 0;
  2711. zend_error(E_WARNING, ACCELERATOR_PRODUCT_NAME ": module registration failed!");
  2712. return FAILURE;
  2713. }
  2714. #ifdef ZEND_WIN32
  2715. if (UNEXPECTED(accel_gen_uname_id() == FAILURE)) {
  2716. zps_startup_failure("Unable to get user name", NULL, accelerator_remove_cb);
  2717. return SUCCESS;
  2718. }
  2719. #endif
  2720. #ifdef HAVE_HUGE_CODE_PAGES
  2721. if (ZCG(accel_directives).huge_code_pages &&
  2722. (strcmp(sapi_module.name, "cli") == 0 ||
  2723. strcmp(sapi_module.name, "cli-server") == 0 ||
  2724. strcmp(sapi_module.name, "cgi-fcgi") == 0 ||
  2725. strcmp(sapi_module.name, "fpm-fcgi") == 0)) {
  2726. accel_move_code_to_huge_pages();
  2727. }
  2728. #endif
  2729. /* no supported SAPI found - disable acceleration and stop initialization */
  2730. if (accel_find_sapi() == FAILURE) {
  2731. accel_startup_ok = 0;
  2732. if (!ZCG(accel_directives).enable_cli &&
  2733. strcmp(sapi_module.name, "cli") == 0) {
  2734. zps_startup_failure("Opcode Caching is disabled for CLI", NULL, accelerator_remove_cb);
  2735. } else {
  2736. zps_startup_failure("Opcode Caching is only supported in Apache, FPM, FastCGI and LiteSpeed SAPIs", NULL, accelerator_remove_cb);
  2737. }
  2738. return SUCCESS;
  2739. }
  2740. if (ZCG(enabled) == 0) {
  2741. return SUCCESS ;
  2742. }
  2743. orig_post_startup_cb = zend_post_startup_cb;
  2744. zend_post_startup_cb = accel_post_startup;
  2745. /* Prevent unloading */
  2746. extension->handle = 0;
  2747. return SUCCESS;
  2748. }
  2749. static zend_result accel_post_startup(void)
  2750. {
  2751. zend_function *func;
  2752. zend_ini_entry *ini_entry;
  2753. if (orig_post_startup_cb) {
  2754. zend_result (*cb)(void) = orig_post_startup_cb;
  2755. orig_post_startup_cb = NULL;
  2756. if (cb() != SUCCESS) {
  2757. return FAILURE;
  2758. }
  2759. }
  2760. /********************************************/
  2761. /* End of non-SHM dependent initializations */
  2762. /********************************************/
  2763. file_cache_only = ZCG(accel_directives).file_cache_only;
  2764. if (!file_cache_only) {
  2765. size_t shm_size = ZCG(accel_directives).memory_consumption;
  2766. #ifdef HAVE_JIT
  2767. size_t jit_size = 0;
  2768. bool reattached = 0;
  2769. if (JIT_G(enabled) && JIT_G(buffer_size)
  2770. && zend_jit_check_support() == SUCCESS) {
  2771. size_t page_size;
  2772. page_size = zend_get_page_size();
  2773. if (!page_size && (page_size & (page_size - 1))) {
  2774. zend_accel_error_noreturn(ACCEL_LOG_FATAL, "Failure to initialize shared memory structures - can't get page size.");
  2775. abort();
  2776. }
  2777. jit_size = JIT_G(buffer_size);
  2778. jit_size = ZEND_MM_ALIGNED_SIZE_EX(jit_size, page_size);
  2779. shm_size += jit_size;
  2780. }
  2781. switch (zend_shared_alloc_startup(shm_size, jit_size)) {
  2782. #else
  2783. switch (zend_shared_alloc_startup(shm_size, 0)) {
  2784. #endif
  2785. case ALLOC_SUCCESS:
  2786. if (zend_accel_init_shm() == FAILURE) {
  2787. accel_startup_ok = 0;
  2788. return FAILURE;
  2789. }
  2790. break;
  2791. case ALLOC_FAILURE:
  2792. accel_startup_ok = 0;
  2793. zend_accel_error_noreturn(ACCEL_LOG_FATAL, "Failure to initialize shared memory structures - probably not enough shared memory.");
  2794. return SUCCESS;
  2795. case SUCCESSFULLY_REATTACHED:
  2796. #ifdef HAVE_JIT
  2797. reattached = 1;
  2798. #endif
  2799. zend_shared_alloc_lock();
  2800. accel_shared_globals = (zend_accel_shared_globals *) ZSMMG(app_shared_globals);
  2801. zend_interned_strings_set_request_storage_handlers(
  2802. accel_new_interned_string_for_php,
  2803. accel_init_interned_string_for_php,
  2804. accel_init_interned_string_for_php);
  2805. zend_shared_alloc_unlock();
  2806. break;
  2807. case FAILED_REATTACHED:
  2808. accel_startup_ok = 0;
  2809. zend_accel_error_noreturn(ACCEL_LOG_FATAL, "Failure to initialize shared memory structures - can not reattach to exiting shared memory.");
  2810. return SUCCESS;
  2811. break;
  2812. #if ENABLE_FILE_CACHE_FALLBACK
  2813. case ALLOC_FALLBACK:
  2814. zend_shared_alloc_lock();
  2815. file_cache_only = 1;
  2816. fallback_process = 1;
  2817. zend_shared_alloc_unlock();
  2818. goto file_cache_fallback;
  2819. break;
  2820. #endif
  2821. }
  2822. /* from this point further, shared memory is supposed to be OK */
  2823. /* remember the last restart time in the process memory */
  2824. ZCG(last_restart_time) = ZCSG(last_restart_time);
  2825. zend_shared_alloc_lock();
  2826. #ifdef HAVE_JIT
  2827. if (JIT_G(enabled)) {
  2828. if (JIT_G(buffer_size) == 0
  2829. || !ZSMMG(reserved)
  2830. || zend_jit_startup(ZSMMG(reserved), jit_size, reattached) != SUCCESS) {
  2831. JIT_G(enabled) = 0;
  2832. JIT_G(on) = 0;
  2833. }
  2834. }
  2835. #endif
  2836. zend_shared_alloc_save_state();
  2837. zend_shared_alloc_unlock();
  2838. SHM_PROTECT();
  2839. } else if (!ZCG(accel_directives).file_cache) {
  2840. accel_startup_ok = 0;
  2841. zend_accel_error_noreturn(ACCEL_LOG_FATAL, "opcache.file_cache_only is set without a proper setting of opcache.file_cache");
  2842. return SUCCESS;
  2843. } else {
  2844. #ifdef HAVE_JIT
  2845. JIT_G(enabled) = 0;
  2846. JIT_G(on) = 0;
  2847. #endif
  2848. accel_shared_globals = calloc(1, sizeof(zend_accel_shared_globals));
  2849. }
  2850. #if ENABLE_FILE_CACHE_FALLBACK
  2851. file_cache_fallback:
  2852. #endif
  2853. /* Override compiler */
  2854. accelerator_orig_compile_file = zend_compile_file;
  2855. zend_compile_file = persistent_compile_file;
  2856. /* Override stream opener function (to eliminate open() call caused by
  2857. * include/require statements ) */
  2858. accelerator_orig_zend_stream_open_function = zend_stream_open_function;
  2859. zend_stream_open_function = persistent_stream_open_function;
  2860. /* Override path resolver function (to eliminate stat() calls caused by
  2861. * include_once/require_once statements */
  2862. accelerator_orig_zend_resolve_path = zend_resolve_path;
  2863. zend_resolve_path = persistent_zend_resolve_path;
  2864. /* Override chdir() function */
  2865. if ((func = zend_hash_str_find_ptr(CG(function_table), "chdir", sizeof("chdir")-1)) != NULL &&
  2866. func->type == ZEND_INTERNAL_FUNCTION) {
  2867. orig_chdir = func->internal_function.handler;
  2868. func->internal_function.handler = ZEND_FN(accel_chdir);
  2869. }
  2870. ZCG(cwd) = NULL;
  2871. ZCG(include_path) = NULL;
  2872. /* Override "include_path" modifier callback */
  2873. if ((ini_entry = zend_hash_str_find_ptr(EG(ini_directives), "include_path", sizeof("include_path")-1)) != NULL) {
  2874. ZCG(include_path) = ini_entry->value;
  2875. orig_include_path_on_modify = ini_entry->on_modify;
  2876. ini_entry->on_modify = accel_include_path_on_modify;
  2877. }
  2878. accel_startup_ok = 1;
  2879. /* Override file_exists(), is_file() and is_readable() */
  2880. zend_accel_override_file_functions();
  2881. /* Load black list */
  2882. accel_blacklist.entries = NULL;
  2883. if (ZCG(enabled) && accel_startup_ok &&
  2884. ZCG(accel_directives).user_blacklist_filename &&
  2885. *ZCG(accel_directives.user_blacklist_filename)) {
  2886. zend_accel_blacklist_init(&accel_blacklist);
  2887. zend_accel_blacklist_load(&accel_blacklist, ZCG(accel_directives.user_blacklist_filename));
  2888. }
  2889. if (!file_cache_only && ZCG(accel_directives).interned_strings_buffer) {
  2890. accel_use_shm_interned_strings();
  2891. }
  2892. if (accel_finish_startup() != SUCCESS) {
  2893. return FAILURE;
  2894. }
  2895. if (ZCG(enabled) && accel_startup_ok) {
  2896. /* Override inheritance cache callbaks */
  2897. accelerator_orig_inheritance_cache_get = zend_inheritance_cache_get;
  2898. accelerator_orig_inheritance_cache_add = zend_inheritance_cache_add;
  2899. zend_inheritance_cache_get = zend_accel_inheritance_cache_get;
  2900. zend_inheritance_cache_add = zend_accel_inheritance_cache_add;
  2901. }
  2902. return SUCCESS;
  2903. }
  2904. static void (*orig_post_shutdown_cb)(void);
  2905. static void accel_post_shutdown(void)
  2906. {
  2907. zend_shared_alloc_shutdown();
  2908. }
  2909. void accel_shutdown(void)
  2910. {
  2911. zend_ini_entry *ini_entry;
  2912. bool _file_cache_only = 0;
  2913. #ifdef HAVE_JIT
  2914. zend_jit_shutdown();
  2915. #endif
  2916. zend_accel_blacklist_shutdown(&accel_blacklist);
  2917. if (!ZCG(enabled) || !accel_startup_ok) {
  2918. #ifdef ZTS
  2919. ts_free_id(accel_globals_id);
  2920. #endif
  2921. return;
  2922. }
  2923. if (ZCSG(preload_script)) {
  2924. preload_shutdown();
  2925. }
  2926. _file_cache_only = file_cache_only;
  2927. accel_reset_pcre_cache();
  2928. #ifdef ZTS
  2929. ts_free_id(accel_globals_id);
  2930. #endif
  2931. if (!_file_cache_only) {
  2932. /* Delay SHM detach */
  2933. orig_post_shutdown_cb = zend_post_shutdown_cb;
  2934. zend_post_shutdown_cb = accel_post_shutdown;
  2935. }
  2936. zend_compile_file = accelerator_orig_compile_file;
  2937. zend_inheritance_cache_get = accelerator_orig_inheritance_cache_get;
  2938. zend_inheritance_cache_add = accelerator_orig_inheritance_cache_add;
  2939. if ((ini_entry = zend_hash_str_find_ptr(EG(ini_directives), "include_path", sizeof("include_path")-1)) != NULL) {
  2940. ini_entry->on_modify = orig_include_path_on_modify;
  2941. }
  2942. }
  2943. void zend_accel_schedule_restart(zend_accel_restart_reason reason)
  2944. {
  2945. const char *zend_accel_restart_reason_text[ACCEL_RESTART_USER + 1] = {
  2946. "out of memory",
  2947. "hash overflow",
  2948. "user",
  2949. };
  2950. if (ZCSG(restart_pending)) {
  2951. /* don't schedule twice */
  2952. return;
  2953. }
  2954. zend_accel_error(ACCEL_LOG_DEBUG, "Restart Scheduled! Reason: %s",
  2955. zend_accel_restart_reason_text[reason]);
  2956. HANDLE_BLOCK_INTERRUPTIONS();
  2957. SHM_UNPROTECT();
  2958. ZCSG(restart_pending) = 1;
  2959. ZCSG(restart_reason) = reason;
  2960. ZCSG(cache_status_before_restart) = ZCSG(accelerator_enabled);
  2961. ZCSG(accelerator_enabled) = 0;
  2962. if (ZCG(accel_directives).force_restart_timeout) {
  2963. ZCSG(force_restart_time) = zend_accel_get_time() + ZCG(accel_directives).force_restart_timeout;
  2964. } else {
  2965. ZCSG(force_restart_time) = 0;
  2966. }
  2967. SHM_PROTECT();
  2968. HANDLE_UNBLOCK_INTERRUPTIONS();
  2969. }
  2970. /* this is needed because on WIN32 lock is not decreased unless ZCG(counted) is set */
  2971. #ifdef ZEND_WIN32
  2972. #define accel_deactivate_now() ZCG(counted) = 1; accel_deactivate_sub()
  2973. #else
  2974. #define accel_deactivate_now() accel_deactivate_sub()
  2975. #endif
  2976. /* ensures it is OK to read SHM
  2977. if it's not OK (restart in progress) returns FAILURE
  2978. if OK returns SUCCESS
  2979. MUST call accelerator_shm_read_unlock after done lock operations
  2980. */
  2981. int accelerator_shm_read_lock(void)
  2982. {
  2983. if (ZCG(counted)) {
  2984. /* counted means we are holding read lock for SHM, so that nothing bad can happen */
  2985. return SUCCESS;
  2986. } else {
  2987. /* here accelerator is active but we do not hold SHM lock. This means restart was scheduled
  2988. or is in progress now */
  2989. if (accel_activate_add() == FAILURE) { /* acquire usage lock */
  2990. return FAILURE;
  2991. }
  2992. /* Now if we weren't inside restart, restart would not begin until we remove usage lock */
  2993. if (ZCSG(restart_in_progress)) {
  2994. /* we already were inside restart this means it's not safe to touch shm */
  2995. accel_deactivate_now(); /* drop usage lock */
  2996. return FAILURE;
  2997. }
  2998. ZCG(counted) = 1;
  2999. }
  3000. return SUCCESS;
  3001. }
  3002. /* must be called ONLY after SUCCESSFUL accelerator_shm_read_lock */
  3003. void accelerator_shm_read_unlock(void)
  3004. {
  3005. if (!ZCG(counted)) {
  3006. /* counted is 0 - meaning we had to readlock manually, release readlock now */
  3007. accel_deactivate_now();
  3008. }
  3009. }
  3010. /* Preloading */
  3011. static HashTable *preload_scripts = NULL;
  3012. static zend_op_array *(*preload_orig_compile_file)(zend_file_handle *file_handle, int type);
  3013. static void preload_shutdown(void)
  3014. {
  3015. zval *zv;
  3016. #if 0
  3017. if (EG(zend_constants)) {
  3018. ZEND_HASH_REVERSE_FOREACH_VAL(EG(zend_constants), zv) {
  3019. zend_constant *c = Z_PTR_P(zv);
  3020. if (ZEND_CONSTANT_FLAGS(c) & CONST_PERSISTENT) {
  3021. break;
  3022. }
  3023. } ZEND_HASH_FOREACH_END_DEL();
  3024. }
  3025. #endif
  3026. if (EG(function_table)) {
  3027. ZEND_HASH_REVERSE_FOREACH_VAL(EG(function_table), zv) {
  3028. zend_function *func = Z_PTR_P(zv);
  3029. if (func->type == ZEND_INTERNAL_FUNCTION) {
  3030. break;
  3031. }
  3032. } ZEND_HASH_FOREACH_END_DEL();
  3033. }
  3034. if (EG(class_table)) {
  3035. ZEND_HASH_REVERSE_FOREACH_VAL(EG(class_table), zv) {
  3036. zend_class_entry *ce = Z_PTR_P(zv);
  3037. if (ce->type == ZEND_INTERNAL_CLASS) {
  3038. break;
  3039. }
  3040. } ZEND_HASH_FOREACH_END_DEL();
  3041. }
  3042. }
  3043. static void preload_activate(void)
  3044. {
  3045. if (ZCSG(preload_script)->ping_auto_globals_mask & ~ZCG(auto_globals_mask)) {
  3046. zend_accel_set_auto_globals(ZCSG(preload_script)->ping_auto_globals_mask & ~ZCG(auto_globals_mask));
  3047. }
  3048. }
  3049. static void preload_restart(void)
  3050. {
  3051. zend_accel_hash_update(&ZCSG(hash), ZCSG(preload_script)->script.filename, 0, ZCSG(preload_script));
  3052. if (ZCSG(saved_scripts)) {
  3053. zend_persistent_script **p = ZCSG(saved_scripts);
  3054. while (*p) {
  3055. zend_accel_hash_update(&ZCSG(hash), (*p)->script.filename, 0, *p);
  3056. p++;
  3057. }
  3058. }
  3059. }
  3060. static size_t preload_try_strip_filename(zend_string *filename) {
  3061. /*FIXME: better way to hanlde eval()'d code? see COMPILED_STRING_DESCRIPTION_FORMAT */
  3062. if (ZSTR_LEN(filename) > sizeof(" eval()'d code")
  3063. && *(ZSTR_VAL(filename) + ZSTR_LEN(filename) - sizeof(" eval()'d code")) == ':') {
  3064. const char *cfilename = ZSTR_VAL(filename);
  3065. size_t cfilenamelen = ZSTR_LEN(filename) - sizeof(" eval()'d code") - 1 /*:*/;
  3066. while (cfilenamelen && cfilename[--cfilenamelen] != '(');
  3067. return cfilenamelen;
  3068. }
  3069. return 0;
  3070. }
  3071. static void preload_move_user_functions(HashTable *src, HashTable *dst)
  3072. {
  3073. Bucket *p;
  3074. dtor_func_t orig_dtor = src->pDestructor;
  3075. zend_string *filename = NULL;
  3076. int copy = 0;
  3077. src->pDestructor = NULL;
  3078. zend_hash_extend(dst, dst->nNumUsed + src->nNumUsed, 0);
  3079. ZEND_HASH_REVERSE_FOREACH_BUCKET(src, p) {
  3080. zend_function *function = Z_PTR(p->val);
  3081. if (EXPECTED(function->type == ZEND_USER_FUNCTION)) {
  3082. if (function->op_array.filename != filename) {
  3083. filename = function->op_array.filename;
  3084. if (filename) {
  3085. if (!(copy = zend_hash_exists(preload_scripts, filename))) {
  3086. size_t eval_len = preload_try_strip_filename(filename);
  3087. if (eval_len) {
  3088. copy = zend_hash_str_exists(preload_scripts, ZSTR_VAL(filename), eval_len);
  3089. }
  3090. }
  3091. } else {
  3092. copy = 0;
  3093. }
  3094. }
  3095. if (copy) {
  3096. _zend_hash_append_ptr(dst, p->key, function);
  3097. } else {
  3098. orig_dtor(&p->val);
  3099. }
  3100. zend_hash_del_bucket(src, p);
  3101. } else {
  3102. break;
  3103. }
  3104. } ZEND_HASH_FOREACH_END();
  3105. src->pDestructor = orig_dtor;
  3106. }
  3107. static void preload_move_user_classes(HashTable *src, HashTable *dst)
  3108. {
  3109. Bucket *p;
  3110. dtor_func_t orig_dtor = src->pDestructor;
  3111. zend_string *filename = NULL;
  3112. int copy = 0;
  3113. src->pDestructor = NULL;
  3114. zend_hash_extend(dst, dst->nNumUsed + src->nNumUsed, 0);
  3115. ZEND_HASH_FOREACH_BUCKET_FROM(src, p, EG(persistent_classes_count)) {
  3116. zend_class_entry *ce = Z_PTR(p->val);
  3117. ZEND_ASSERT(ce->type == ZEND_USER_CLASS);
  3118. if (ce->info.user.filename != filename) {
  3119. filename = ce->info.user.filename;
  3120. if (filename) {
  3121. if (!(copy = zend_hash_exists(preload_scripts, filename))) {
  3122. size_t eval_len = preload_try_strip_filename(filename);
  3123. if (eval_len) {
  3124. copy = zend_hash_str_exists(preload_scripts, ZSTR_VAL(filename), eval_len);
  3125. }
  3126. }
  3127. } else {
  3128. copy = 0;
  3129. }
  3130. }
  3131. if (copy) {
  3132. _zend_hash_append(dst, p->key, &p->val);
  3133. } else {
  3134. orig_dtor(&p->val);
  3135. }
  3136. zend_hash_del_bucket(src, p);
  3137. } ZEND_HASH_FOREACH_END();
  3138. src->pDestructor = orig_dtor;
  3139. }
  3140. static zend_op_array *preload_compile_file(zend_file_handle *file_handle, int type)
  3141. {
  3142. zend_op_array *op_array = preload_orig_compile_file(file_handle, type);
  3143. if (op_array && op_array->refcount) {
  3144. zend_persistent_script *script;
  3145. script = create_persistent_script();
  3146. script->script.first_early_binding_opline = (uint32_t)-1;
  3147. script->script.filename = zend_string_copy(op_array->filename);
  3148. zend_string_hash_val(script->script.filename);
  3149. script->script.main_op_array = *op_array;
  3150. //??? efree(op_array->refcount);
  3151. op_array->refcount = NULL;
  3152. zend_hash_add_ptr(preload_scripts, script->script.filename, script);
  3153. }
  3154. return op_array;
  3155. }
  3156. static void preload_sort_classes(void *base, size_t count, size_t siz, compare_func_t compare, swap_func_t swp)
  3157. {
  3158. Bucket *b1 = base;
  3159. Bucket *b2;
  3160. Bucket *end = b1 + count;
  3161. Bucket tmp;
  3162. zend_class_entry *ce, *p;
  3163. while (b1 < end) {
  3164. try_again:
  3165. ce = (zend_class_entry*)Z_PTR(b1->val);
  3166. if (ce->parent && (ce->ce_flags & ZEND_ACC_LINKED)) {
  3167. p = ce->parent;
  3168. if (p->type == ZEND_USER_CLASS) {
  3169. b2 = b1 + 1;
  3170. while (b2 < end) {
  3171. if (p == Z_PTR(b2->val)) {
  3172. tmp = *b1;
  3173. *b1 = *b2;
  3174. *b2 = tmp;
  3175. goto try_again;
  3176. }
  3177. b2++;
  3178. }
  3179. }
  3180. }
  3181. if (ce->num_interfaces && (ce->ce_flags & ZEND_ACC_LINKED)) {
  3182. uint32_t i = 0;
  3183. for (i = 0; i < ce->num_interfaces; i++) {
  3184. p = ce->interfaces[i];
  3185. if (p->type == ZEND_USER_CLASS) {
  3186. b2 = b1 + 1;
  3187. while (b2 < end) {
  3188. if (p == Z_PTR(b2->val)) {
  3189. tmp = *b1;
  3190. *b1 = *b2;
  3191. *b2 = tmp;
  3192. goto try_again;
  3193. }
  3194. b2++;
  3195. }
  3196. }
  3197. }
  3198. }
  3199. b1++;
  3200. }
  3201. }
  3202. typedef struct {
  3203. const char *kind;
  3204. const char *name;
  3205. } preload_error;
  3206. static zend_result preload_resolve_deps(preload_error *error, const zend_class_entry *ce)
  3207. {
  3208. memset(error, 0, sizeof(preload_error));
  3209. if (ce->parent_name) {
  3210. zend_string *key = zend_string_tolower(ce->parent_name);
  3211. zend_class_entry *parent = zend_hash_find_ptr(EG(class_table), key);
  3212. zend_string_release(key);
  3213. if (!parent) {
  3214. error->kind = "Unknown parent ";
  3215. error->name = ZSTR_VAL(ce->parent_name);
  3216. return FAILURE;
  3217. }
  3218. }
  3219. if (ce->num_interfaces) {
  3220. for (uint32_t i = 0; i < ce->num_interfaces; i++) {
  3221. zend_class_entry *interface =
  3222. zend_hash_find_ptr(EG(class_table), ce->interface_names[i].lc_name);
  3223. if (!interface) {
  3224. error->kind = "Unknown interface ";
  3225. error->name = ZSTR_VAL(ce->interface_names[i].name);
  3226. return FAILURE;
  3227. }
  3228. }
  3229. }
  3230. if (ce->num_traits) {
  3231. for (uint32_t i = 0; i < ce->num_traits; i++) {
  3232. zend_class_entry *trait =
  3233. zend_hash_find_ptr(EG(class_table), ce->trait_names[i].lc_name);
  3234. if (!trait) {
  3235. error->kind = "Unknown trait ";
  3236. error->name = ZSTR_VAL(ce->trait_names[i].name);
  3237. return FAILURE;
  3238. }
  3239. }
  3240. }
  3241. return SUCCESS;
  3242. }
  3243. static bool preload_try_resolve_constants(zend_class_entry *ce)
  3244. {
  3245. bool ok, changed, was_changed = 0;
  3246. zend_class_constant *c;
  3247. zval *val;
  3248. EG(exception) = (void*)(uintptr_t)-1; /* prevent error reporting */
  3249. do {
  3250. ok = 1;
  3251. changed = 0;
  3252. ZEND_HASH_FOREACH_PTR(&ce->constants_table, c) {
  3253. val = &c->value;
  3254. if (Z_TYPE_P(val) == IS_CONSTANT_AST) {
  3255. if (EXPECTED(zval_update_constant_ex(val, c->ce) == SUCCESS)) {
  3256. was_changed = changed = 1;
  3257. } else {
  3258. ok = 0;
  3259. }
  3260. }
  3261. } ZEND_HASH_FOREACH_END();
  3262. if (ok) {
  3263. ce->ce_flags &= ~ZEND_ACC_HAS_AST_CONSTANTS;
  3264. }
  3265. if (ce->default_properties_count) {
  3266. uint32_t i;
  3267. bool resolved = 1;
  3268. for (i = 0; i < ce->default_properties_count; i++) {
  3269. val = &ce->default_properties_table[i];
  3270. if (Z_TYPE_P(val) == IS_CONSTANT_AST) {
  3271. zend_property_info *prop = ce->properties_info_table[i];
  3272. if (UNEXPECTED(zval_update_constant_ex(val, prop->ce) != SUCCESS)) {
  3273. resolved = ok = 0;
  3274. }
  3275. }
  3276. }
  3277. if (resolved) {
  3278. ce->ce_flags &= ~ZEND_ACC_HAS_AST_PROPERTIES;
  3279. }
  3280. }
  3281. if (ce->default_static_members_count) {
  3282. uint32_t count = ce->parent ? ce->default_static_members_count - ce->parent->default_static_members_count : ce->default_static_members_count;
  3283. bool resolved = 1;
  3284. val = ce->default_static_members_table + ce->default_static_members_count - 1;
  3285. while (count) {
  3286. if (Z_TYPE_P(val) == IS_CONSTANT_AST) {
  3287. if (UNEXPECTED(zval_update_constant_ex(val, ce) != SUCCESS)) {
  3288. resolved = ok = 0;
  3289. }
  3290. }
  3291. val--;
  3292. count--;
  3293. }
  3294. if (resolved) {
  3295. ce->ce_flags &= ~ZEND_ACC_HAS_AST_STATICS;
  3296. }
  3297. }
  3298. } while (changed && !ok);
  3299. EG(exception) = NULL;
  3300. CG(in_compilation) = 0;
  3301. if (ok) {
  3302. ce->ce_flags |= ZEND_ACC_CONSTANTS_UPDATED;
  3303. }
  3304. return ok || was_changed;
  3305. }
  3306. static void (*orig_error_cb)(int type, zend_string *error_filename, const uint32_t error_lineno, zend_string *message);
  3307. static void preload_error_cb(int type, zend_string *error_filename, const uint32_t error_lineno, zend_string *message)
  3308. {
  3309. /* Suppress printing of the error, only bail out for fatal errors. */
  3310. if (type & E_FATAL_ERRORS) {
  3311. zend_bailout();
  3312. }
  3313. }
  3314. /* Remove DECLARE opcodes and dynamic defs. */
  3315. static void preload_remove_declares(zend_op_array *op_array)
  3316. {
  3317. zend_op *opline = op_array->opcodes;
  3318. zend_op *end = opline + op_array->last;
  3319. uint32_t skip_dynamic_func_count = 0;
  3320. zend_string *key;
  3321. zend_op_array *func;
  3322. while (opline != end) {
  3323. switch (opline->opcode) {
  3324. case ZEND_DECLARE_CLASS:
  3325. case ZEND_DECLARE_CLASS_DELAYED:
  3326. key = Z_STR_P(RT_CONSTANT(opline, opline->op1) + 1);
  3327. if (!zend_hash_exists(CG(class_table), key)) {
  3328. MAKE_NOP(opline);
  3329. }
  3330. break;
  3331. case ZEND_DECLARE_FUNCTION:
  3332. opline->op2.num -= skip_dynamic_func_count;
  3333. key = Z_STR_P(RT_CONSTANT(opline, opline->op1));
  3334. func = zend_hash_find_ptr(EG(function_table), key);
  3335. if (func && func == op_array->dynamic_func_defs[opline->op2.num]) {
  3336. zend_op_array **dynamic_func_defs;
  3337. op_array->num_dynamic_func_defs--;
  3338. if (op_array->num_dynamic_func_defs == 0) {
  3339. dynamic_func_defs = NULL;
  3340. } else {
  3341. dynamic_func_defs = emalloc(sizeof(zend_op_array*) * op_array->num_dynamic_func_defs);
  3342. if (opline->op2.num > 0) {
  3343. memcpy(
  3344. dynamic_func_defs,
  3345. op_array->dynamic_func_defs,
  3346. sizeof(zend_op_array*) * opline->op2.num);
  3347. }
  3348. if (op_array->num_dynamic_func_defs - opline->op2.num > 0) {
  3349. memcpy(
  3350. dynamic_func_defs + opline->op2.num,
  3351. op_array->dynamic_func_defs + (opline->op2.num + 1),
  3352. sizeof(zend_op_array*) * (op_array->num_dynamic_func_defs - opline->op2.num));
  3353. }
  3354. }
  3355. efree(op_array->dynamic_func_defs);
  3356. op_array->dynamic_func_defs = dynamic_func_defs;
  3357. skip_dynamic_func_count++;
  3358. MAKE_NOP(opline);
  3359. }
  3360. break;
  3361. case ZEND_DECLARE_LAMBDA_FUNCTION:
  3362. opline->op2.num -= skip_dynamic_func_count;
  3363. break;
  3364. }
  3365. opline++;
  3366. }
  3367. }
  3368. static void preload_link(void)
  3369. {
  3370. zval *zv;
  3371. zend_persistent_script *script;
  3372. zend_class_entry *ce;
  3373. zend_string *key;
  3374. bool changed;
  3375. HashTable errors;
  3376. zend_hash_init(&errors, 0, NULL, NULL, 0);
  3377. /* Resolve class dependencies */
  3378. do {
  3379. changed = 0;
  3380. ZEND_HASH_FOREACH_STR_KEY_VAL_FROM(EG(class_table), key, zv, EG(persistent_classes_count)) {
  3381. ce = Z_PTR_P(zv);
  3382. ZEND_ASSERT(ce->type != ZEND_INTERNAL_CLASS);
  3383. if ((ce->ce_flags & (ZEND_ACC_TOP_LEVEL|ZEND_ACC_ANON_CLASS))
  3384. && !(ce->ce_flags & ZEND_ACC_LINKED)) {
  3385. zend_string *lcname = zend_string_tolower(ce->name);
  3386. if (!(ce->ce_flags & ZEND_ACC_ANON_CLASS)) {
  3387. if (zend_hash_exists(EG(class_table), lcname)) {
  3388. zend_string_release(lcname);
  3389. continue;
  3390. }
  3391. }
  3392. preload_error error_info;
  3393. if (preload_resolve_deps(&error_info, ce) == FAILURE) {
  3394. zend_string_release(lcname);
  3395. continue;
  3396. }
  3397. zv = zend_hash_set_bucket_key(EG(class_table), (Bucket*)zv, lcname);
  3398. if (EXPECTED(zv)) {
  3399. /* Set the FILE_CACHED flag to force a lazy load, and the CACHED flag to
  3400. * prevent freeing of interface names. */
  3401. void *checkpoint = zend_arena_checkpoint(CG(arena));
  3402. zend_class_entry *orig_ce = ce;
  3403. uint32_t temporary_flags = ZEND_ACC_FILE_CACHED|ZEND_ACC_CACHED;
  3404. ce->ce_flags |= temporary_flags;
  3405. if (ce->parent_name) {
  3406. zend_string_addref(ce->parent_name);
  3407. }
  3408. /* Record and suppress errors during inheritance. */
  3409. orig_error_cb = zend_error_cb;
  3410. zend_error_cb = preload_error_cb;
  3411. zend_begin_record_errors();
  3412. /* Set filename & lineno information for inheritance errors */
  3413. CG(in_compilation) = 1;
  3414. CG(compiled_filename) = ce->info.user.filename;
  3415. CG(zend_lineno) = ce->info.user.line_start;
  3416. zend_try {
  3417. ce = zend_do_link_class(ce, NULL, lcname);
  3418. if (!ce) {
  3419. ZEND_ASSERT(0 && "Class linking failed?");
  3420. }
  3421. ce->ce_flags &= ~temporary_flags;
  3422. changed = true;
  3423. /* Inheritance successful, print out any warnings. */
  3424. zend_error_cb = orig_error_cb;
  3425. zend_emit_recorded_errors();
  3426. } zend_catch {
  3427. /* Clear variance obligations that were left behind on bailout. */
  3428. if (CG(delayed_variance_obligations)) {
  3429. zend_hash_index_del(
  3430. CG(delayed_variance_obligations), (uintptr_t) Z_CE_P(zv));
  3431. }
  3432. /* Restore the original class. */
  3433. zv = zend_hash_set_bucket_key(EG(class_table), (Bucket*)zv, key);
  3434. Z_CE_P(zv) = orig_ce;
  3435. orig_ce->ce_flags &= ~temporary_flags;
  3436. zend_arena_release(&CG(arena), checkpoint);
  3437. /* Remember the last error. */
  3438. zend_error_cb = orig_error_cb;
  3439. EG(record_errors) = false;
  3440. ZEND_ASSERT(EG(num_errors) > 0);
  3441. zend_hash_update_ptr(&errors, key, EG(errors)[EG(num_errors)-1]);
  3442. EG(num_errors)--;
  3443. } zend_end_try();
  3444. CG(in_compilation) = 0;
  3445. CG(compiled_filename) = NULL;
  3446. zend_free_recorded_errors();
  3447. }
  3448. zend_string_release(lcname);
  3449. }
  3450. } ZEND_HASH_FOREACH_END();
  3451. } while (changed);
  3452. do {
  3453. changed = 0;
  3454. ZEND_HASH_REVERSE_FOREACH_VAL(EG(class_table), zv) {
  3455. ce = Z_PTR_P(zv);
  3456. if (ce->type == ZEND_INTERNAL_CLASS) {
  3457. break;
  3458. }
  3459. if (!(ce->ce_flags & ZEND_ACC_CONSTANTS_UPDATED)) {
  3460. if (!(ce->ce_flags & ZEND_ACC_TRAIT)) { /* don't update traits */
  3461. CG(in_compilation) = 1; /* prevent autoloading */
  3462. if (preload_try_resolve_constants(ce)) {
  3463. changed = 1;
  3464. }
  3465. CG(in_compilation) = 0;
  3466. }
  3467. }
  3468. } ZEND_HASH_FOREACH_END();
  3469. } while (changed);
  3470. /* Warn for classes that could not be linked. */
  3471. ZEND_HASH_FOREACH_STR_KEY_VAL_FROM(
  3472. EG(class_table), key, zv, EG(persistent_classes_count)) {
  3473. ce = Z_PTR_P(zv);
  3474. ZEND_ASSERT(ce->type != ZEND_INTERNAL_CLASS);
  3475. if ((ce->ce_flags & (ZEND_ACC_TOP_LEVEL|ZEND_ACC_ANON_CLASS))
  3476. && !(ce->ce_flags & ZEND_ACC_LINKED)) {
  3477. zend_string *lcname = zend_string_tolower(ce->name);
  3478. preload_error error;
  3479. if (!(ce->ce_flags & ZEND_ACC_ANON_CLASS)
  3480. && zend_hash_exists(EG(class_table), lcname)) {
  3481. zend_error_at(
  3482. E_WARNING, ce->info.user.filename, ce->info.user.line_start,
  3483. "Can't preload already declared class %s", ZSTR_VAL(ce->name));
  3484. } else if (preload_resolve_deps(&error, ce)) {
  3485. zend_error_at(
  3486. E_WARNING, ce->info.user.filename, ce->info.user.line_start,
  3487. "Can't preload unlinked class %s: %s%s",
  3488. ZSTR_VAL(ce->name), error.kind, error.name);
  3489. } else {
  3490. zend_error_info *error = zend_hash_find_ptr(&errors, key);
  3491. zend_error_at(
  3492. E_WARNING, error->filename, error->lineno,
  3493. "Can't preload unlinked class %s: %s",
  3494. ZSTR_VAL(ce->name), ZSTR_VAL(error->message));
  3495. }
  3496. zend_string_release(lcname);
  3497. }
  3498. } ZEND_HASH_FOREACH_END();
  3499. zend_hash_destroy(&errors);
  3500. ZEND_HASH_FOREACH_PTR(preload_scripts, script) {
  3501. zend_op_array *op_array = &script->script.main_op_array;
  3502. preload_remove_declares(op_array);
  3503. if (op_array->fn_flags & ZEND_ACC_EARLY_BINDING) {
  3504. script->script.first_early_binding_opline = zend_build_delayed_early_binding_list(op_array);
  3505. if (script->script.first_early_binding_opline == (uint32_t)-1) {
  3506. op_array->fn_flags &= ~ZEND_ACC_EARLY_BINDING;
  3507. }
  3508. }
  3509. } ZEND_HASH_FOREACH_END();
  3510. /* Dynamic defs inside functions and methods need to be removed as well. */
  3511. zend_op_array *op_array;
  3512. ZEND_HASH_FOREACH_PTR_FROM(EG(function_table), op_array, EG(persistent_functions_count)) {
  3513. ZEND_ASSERT(op_array->type == ZEND_USER_FUNCTION);
  3514. preload_remove_declares(op_array);
  3515. } ZEND_HASH_FOREACH_END();
  3516. ZEND_HASH_FOREACH_PTR_FROM(EG(class_table), ce, EG(persistent_classes_count)) {
  3517. ZEND_HASH_FOREACH_PTR(&ce->function_table, op_array) {
  3518. if (op_array->type == ZEND_USER_FUNCTION) {
  3519. preload_remove_declares(op_array);
  3520. }
  3521. } ZEND_HASH_FOREACH_END();
  3522. } ZEND_HASH_FOREACH_END();
  3523. }
  3524. static zend_string *preload_resolve_path(zend_string *filename)
  3525. {
  3526. if (is_stream_path(ZSTR_VAL(filename))) {
  3527. return NULL;
  3528. }
  3529. return zend_resolve_path(filename);
  3530. }
  3531. static void preload_remove_empty_includes(void)
  3532. {
  3533. zend_persistent_script *script;
  3534. bool changed;
  3535. /* mark all as empty */
  3536. ZEND_HASH_FOREACH_PTR(preload_scripts, script) {
  3537. script->empty = 1;
  3538. } ZEND_HASH_FOREACH_END();
  3539. /* find non empty scripts */
  3540. do {
  3541. changed = 0;
  3542. ZEND_HASH_FOREACH_PTR(preload_scripts, script) {
  3543. if (script->empty) {
  3544. int empty = 1;
  3545. zend_op *opline = script->script.main_op_array.opcodes;
  3546. zend_op *end = opline + script->script.main_op_array.last;
  3547. while (opline < end) {
  3548. if (opline->opcode == ZEND_INCLUDE_OR_EVAL &&
  3549. opline->extended_value != ZEND_EVAL &&
  3550. opline->op1_type == IS_CONST &&
  3551. Z_TYPE_P(RT_CONSTANT(opline, opline->op1)) == IS_STRING &&
  3552. opline->result_type == IS_UNUSED) {
  3553. zend_string *resolved_path = preload_resolve_path(Z_STR_P(RT_CONSTANT(opline, opline->op1)));
  3554. if (resolved_path) {
  3555. zend_persistent_script *incl = zend_hash_find_ptr(preload_scripts, resolved_path);
  3556. zend_string_release(resolved_path);
  3557. if (!incl || !incl->empty) {
  3558. empty = 0;
  3559. break;
  3560. }
  3561. } else {
  3562. empty = 0;
  3563. break;
  3564. }
  3565. } else if (opline->opcode != ZEND_NOP &&
  3566. opline->opcode != ZEND_RETURN &&
  3567. opline->opcode != ZEND_HANDLE_EXCEPTION) {
  3568. empty = 0;
  3569. break;
  3570. }
  3571. opline++;
  3572. }
  3573. if (!empty) {
  3574. script->empty = 0;
  3575. changed = 1;
  3576. }
  3577. }
  3578. } ZEND_HASH_FOREACH_END();
  3579. } while (changed);
  3580. /* remove empty includes */
  3581. ZEND_HASH_FOREACH_PTR(preload_scripts, script) {
  3582. zend_op *opline = script->script.main_op_array.opcodes;
  3583. zend_op *end = opline + script->script.main_op_array.last;
  3584. while (opline < end) {
  3585. if (opline->opcode == ZEND_INCLUDE_OR_EVAL &&
  3586. opline->extended_value != ZEND_EVAL &&
  3587. opline->op1_type == IS_CONST &&
  3588. Z_TYPE_P(RT_CONSTANT(opline, opline->op1)) == IS_STRING) {
  3589. zend_string *resolved_path = preload_resolve_path(Z_STR_P(RT_CONSTANT(opline, opline->op1)));
  3590. if (resolved_path) {
  3591. zend_persistent_script *incl = zend_hash_find_ptr(preload_scripts, resolved_path);
  3592. if (incl && incl->empty && opline->result_type == IS_UNUSED) {
  3593. MAKE_NOP(opline);
  3594. } else {
  3595. if (!IS_ABSOLUTE_PATH(Z_STRVAL_P(RT_CONSTANT(opline, opline->op1)), Z_STRLEN_P(RT_CONSTANT(opline, opline->op1)))) {
  3596. /* replace relative patch with absolute one */
  3597. zend_string_release(Z_STR_P(RT_CONSTANT(opline, opline->op1)));
  3598. ZVAL_STR_COPY(RT_CONSTANT(opline, opline->op1), resolved_path);
  3599. }
  3600. }
  3601. zend_string_release(resolved_path);
  3602. }
  3603. }
  3604. opline++;
  3605. }
  3606. } ZEND_HASH_FOREACH_END();
  3607. }
  3608. static void preload_register_trait_methods(zend_class_entry *ce) {
  3609. zend_op_array *op_array;
  3610. ZEND_HASH_FOREACH_PTR(&ce->function_table, op_array) {
  3611. if (!(op_array->fn_flags & ZEND_ACC_TRAIT_CLONE)) {
  3612. ZEND_ASSERT(op_array->refcount && "Must have refcount pointer");
  3613. zend_shared_alloc_register_xlat_entry(op_array->refcount, op_array);
  3614. }
  3615. } ZEND_HASH_FOREACH_END();
  3616. }
  3617. static void preload_fix_trait_methods(zend_class_entry *ce)
  3618. {
  3619. zend_op_array *op_array;
  3620. ZEND_HASH_FOREACH_PTR(&ce->function_table, op_array) {
  3621. if (op_array->fn_flags & ZEND_ACC_TRAIT_CLONE) {
  3622. zend_op_array *orig_op_array = zend_shared_alloc_get_xlat_entry(op_array->refcount);
  3623. ZEND_ASSERT(orig_op_array && "Must be in xlat table");
  3624. zend_string *function_name = op_array->function_name;
  3625. zend_class_entry *scope = op_array->scope;
  3626. uint32_t fn_flags = op_array->fn_flags;
  3627. zend_function *prototype = op_array->prototype;
  3628. HashTable *ht = op_array->static_variables;
  3629. *op_array = *orig_op_array;
  3630. op_array->function_name = function_name;
  3631. op_array->scope = scope;
  3632. op_array->fn_flags = fn_flags;
  3633. op_array->prototype = prototype;
  3634. op_array->static_variables = ht;
  3635. }
  3636. } ZEND_HASH_FOREACH_END();
  3637. }
  3638. static int preload_optimize(zend_persistent_script *script)
  3639. {
  3640. zend_class_entry *ce;
  3641. zend_persistent_script *tmp_script;
  3642. zend_shared_alloc_init_xlat_table();
  3643. ZEND_HASH_FOREACH_PTR(&script->script.class_table, ce) {
  3644. if (ce->ce_flags & ZEND_ACC_TRAIT) {
  3645. preload_register_trait_methods(ce);
  3646. }
  3647. } ZEND_HASH_FOREACH_END();
  3648. ZEND_HASH_FOREACH_PTR(preload_scripts, tmp_script) {
  3649. ZEND_HASH_FOREACH_PTR(&tmp_script->script.class_table, ce) {
  3650. if (ce->ce_flags & ZEND_ACC_TRAIT) {
  3651. preload_register_trait_methods(ce);
  3652. }
  3653. } ZEND_HASH_FOREACH_END();
  3654. } ZEND_HASH_FOREACH_END();
  3655. if (!zend_optimize_script(&script->script, ZCG(accel_directives).optimization_level, ZCG(accel_directives).opt_debug_level)) {
  3656. return FAILURE;
  3657. }
  3658. ZEND_HASH_FOREACH_PTR(&script->script.class_table, ce) {
  3659. preload_fix_trait_methods(ce);
  3660. } ZEND_HASH_FOREACH_END();
  3661. ZEND_HASH_FOREACH_PTR(preload_scripts, script) {
  3662. ZEND_HASH_FOREACH_PTR(&script->script.class_table, ce) {
  3663. preload_fix_trait_methods(ce);
  3664. } ZEND_HASH_FOREACH_END();
  3665. } ZEND_HASH_FOREACH_END();
  3666. zend_shared_alloc_destroy_xlat_table();
  3667. ZEND_HASH_FOREACH_PTR(preload_scripts, script) {
  3668. if (!zend_optimize_script(&script->script, ZCG(accel_directives).optimization_level, ZCG(accel_directives).opt_debug_level)) {
  3669. return FAILURE;
  3670. }
  3671. } ZEND_HASH_FOREACH_END();
  3672. return SUCCESS;
  3673. }
  3674. static zend_persistent_script* preload_script_in_shared_memory(zend_persistent_script *new_persistent_script)
  3675. {
  3676. zend_accel_hash_entry *bucket;
  3677. uint32_t memory_used;
  3678. uint32_t checkpoint;
  3679. if (zend_accel_hash_is_full(&ZCSG(hash))) {
  3680. zend_accel_error_noreturn(ACCEL_LOG_FATAL, "Not enough entries in hash table for preloading. Consider increasing the value for the opcache.max_accelerated_files directive in php.ini.");
  3681. return NULL;
  3682. }
  3683. checkpoint = zend_shared_alloc_checkpoint_xlat_table();
  3684. /* Calculate the required memory size */
  3685. memory_used = zend_accel_script_persist_calc(new_persistent_script, 1);
  3686. /* Allocate shared memory */
  3687. #if defined(__AVX__) || defined(__SSE2__)
  3688. /* Align to 64-byte boundary */
  3689. ZCG(mem) = zend_shared_alloc(memory_used + 64);
  3690. if (ZCG(mem)) {
  3691. ZCG(mem) = (void*)(((zend_uintptr_t)ZCG(mem) + 63L) & ~63L);
  3692. #if defined(__x86_64__)
  3693. memset(ZCG(mem), 0, memory_used);
  3694. #elif defined(__AVX__)
  3695. {
  3696. char *p = (char*)ZCG(mem);
  3697. char *end = p + memory_used;
  3698. __m256i ymm0 = _mm256_setzero_si256();
  3699. while (p < end) {
  3700. _mm256_store_si256((__m256i*)p, ymm0);
  3701. _mm256_store_si256((__m256i*)(p+32), ymm0);
  3702. p += 64;
  3703. }
  3704. }
  3705. #else
  3706. {
  3707. char *p = (char*)ZCG(mem);
  3708. char *end = p + memory_used;
  3709. __m128i xmm0 = _mm_setzero_si128();
  3710. while (p < end) {
  3711. _mm_store_si128((__m128i*)p, xmm0);
  3712. _mm_store_si128((__m128i*)(p+16), xmm0);
  3713. _mm_store_si128((__m128i*)(p+32), xmm0);
  3714. _mm_store_si128((__m128i*)(p+48), xmm0);
  3715. p += 64;
  3716. }
  3717. }
  3718. #endif
  3719. }
  3720. #else
  3721. ZCG(mem) = zend_shared_alloc(memory_used);
  3722. if (ZCG(mem)) {
  3723. memset(ZCG(mem), 0, memory_used);
  3724. }
  3725. #endif
  3726. if (!ZCG(mem)) {
  3727. zend_accel_error_noreturn(ACCEL_LOG_FATAL, "Not enough shared memory for preloading. Consider increasing the value for the opcache.memory_consumption directive in php.ini.");
  3728. return NULL;
  3729. }
  3730. zend_shared_alloc_restore_xlat_table(checkpoint);
  3731. /* Copy into shared memory */
  3732. new_persistent_script = zend_accel_script_persist(new_persistent_script, 1);
  3733. new_persistent_script->is_phar = is_phar_file(new_persistent_script->script.filename);
  3734. /* Consistency check */
  3735. if ((char*)new_persistent_script->mem + new_persistent_script->size != (char*)ZCG(mem)) {
  3736. zend_accel_error(
  3737. ((char*)new_persistent_script->mem + new_persistent_script->size < (char*)ZCG(mem)) ? ACCEL_LOG_ERROR : ACCEL_LOG_WARNING,
  3738. "Internal error: wrong size calculation: %s start=" ZEND_ADDR_FMT ", end=" ZEND_ADDR_FMT ", real=" ZEND_ADDR_FMT "\n",
  3739. ZSTR_VAL(new_persistent_script->script.filename),
  3740. (size_t)new_persistent_script->mem,
  3741. (size_t)((char *)new_persistent_script->mem + new_persistent_script->size),
  3742. (size_t)ZCG(mem));
  3743. }
  3744. new_persistent_script->dynamic_members.checksum = zend_accel_script_checksum(new_persistent_script);
  3745. /* store script structure in the hash table */
  3746. bucket = zend_accel_hash_update(&ZCSG(hash), new_persistent_script->script.filename, 0, new_persistent_script);
  3747. if (bucket) {
  3748. zend_accel_error(ACCEL_LOG_INFO, "Cached script '%s'", ZSTR_VAL(new_persistent_script->script.filename));
  3749. }
  3750. new_persistent_script->dynamic_members.memory_consumption = ZEND_ALIGNED_SIZE(new_persistent_script->size);
  3751. return new_persistent_script;
  3752. }
  3753. static void preload_load(void)
  3754. {
  3755. /* Load into process tables */
  3756. zend_script *script = &ZCSG(preload_script)->script;
  3757. if (zend_hash_num_elements(&script->function_table)) {
  3758. Bucket *p = script->function_table.arData;
  3759. Bucket *end = p + script->function_table.nNumUsed;
  3760. zend_hash_extend(CG(function_table),
  3761. CG(function_table)->nNumUsed + script->function_table.nNumUsed, 0);
  3762. for (; p != end; p++) {
  3763. _zend_hash_append_ptr_ex(CG(function_table), p->key, Z_PTR(p->val), 1);
  3764. }
  3765. }
  3766. if (zend_hash_num_elements(&script->class_table)) {
  3767. Bucket *p = script->class_table.arData;
  3768. Bucket *end = p + script->class_table.nNumUsed;
  3769. zend_hash_extend(CG(class_table),
  3770. CG(class_table)->nNumUsed + script->class_table.nNumUsed, 0);
  3771. for (; p != end; p++) {
  3772. _zend_hash_append_ex(CG(class_table), p->key, &p->val, 1);
  3773. }
  3774. }
  3775. if (EG(zend_constants)) {
  3776. EG(persistent_constants_count) = EG(zend_constants)->nNumUsed;
  3777. }
  3778. if (EG(function_table)) {
  3779. EG(persistent_functions_count) = EG(function_table)->nNumUsed;
  3780. }
  3781. if (EG(class_table)) {
  3782. EG(persistent_classes_count) = EG(class_table)->nNumUsed;
  3783. }
  3784. if (CG(map_ptr_last) != ZCSG(map_ptr_last)) {
  3785. size_t old_map_ptr_last = CG(map_ptr_last);
  3786. CG(map_ptr_last) = ZCSG(map_ptr_last);
  3787. CG(map_ptr_size) = ZEND_MM_ALIGNED_SIZE_EX(CG(map_ptr_last) + 1, 4096);
  3788. CG(map_ptr_real_base) = perealloc(CG(map_ptr_real_base), CG(map_ptr_size) * sizeof(void*), 1);
  3789. CG(map_ptr_base) = ZEND_MAP_PTR_BIASED_BASE(CG(map_ptr_real_base));
  3790. memset((void **) CG(map_ptr_real_base) + old_map_ptr_last, 0,
  3791. (CG(map_ptr_last) - old_map_ptr_last) * sizeof(void *));
  3792. }
  3793. }
  3794. static int accel_preload(const char *config, bool in_child)
  3795. {
  3796. zend_file_handle file_handle;
  3797. int ret;
  3798. char *orig_open_basedir;
  3799. size_t orig_map_ptr_last;
  3800. uint32_t orig_compiler_options;
  3801. ZCG(enabled) = 0;
  3802. ZCG(accelerator_enabled) = 0;
  3803. orig_open_basedir = PG(open_basedir);
  3804. PG(open_basedir) = NULL;
  3805. preload_orig_compile_file = accelerator_orig_compile_file;
  3806. accelerator_orig_compile_file = preload_compile_file;
  3807. orig_map_ptr_last = CG(map_ptr_last);
  3808. /* Compile and execute proloading script */
  3809. zend_stream_init_filename(&file_handle, (char *) config);
  3810. preload_scripts = emalloc(sizeof(HashTable));
  3811. zend_hash_init(preload_scripts, 0, NULL, NULL, 0);
  3812. orig_compiler_options = CG(compiler_options);
  3813. if (in_child) {
  3814. CG(compiler_options) |= ZEND_COMPILE_PRELOAD_IN_CHILD;
  3815. }
  3816. CG(compiler_options) |= ZEND_COMPILE_PRELOAD;
  3817. CG(compiler_options) |= ZEND_COMPILE_HANDLE_OP_ARRAY;
  3818. CG(compiler_options) |= ZEND_COMPILE_DELAYED_BINDING;
  3819. CG(compiler_options) |= ZEND_COMPILE_NO_CONSTANT_SUBSTITUTION;
  3820. CG(compiler_options) |= ZEND_COMPILE_IGNORE_OTHER_FILES;
  3821. CG(skip_shebang) = 1;
  3822. zend_try {
  3823. zend_op_array *op_array;
  3824. ret = SUCCESS;
  3825. op_array = zend_compile_file(&file_handle, ZEND_REQUIRE);
  3826. if (file_handle.opened_path) {
  3827. zend_hash_add_empty_element(&EG(included_files), file_handle.opened_path);
  3828. }
  3829. zend_destroy_file_handle(&file_handle);
  3830. if (op_array) {
  3831. zend_execute(op_array, NULL);
  3832. zend_exception_restore();
  3833. if (UNEXPECTED(EG(exception))) {
  3834. if (Z_TYPE(EG(user_exception_handler)) != IS_UNDEF) {
  3835. zend_user_exception_handler();
  3836. }
  3837. if (EG(exception)) {
  3838. ret = zend_exception_error(EG(exception), E_ERROR);
  3839. if (ret == FAILURE) {
  3840. CG(unclean_shutdown) = 1;
  3841. }
  3842. }
  3843. }
  3844. destroy_op_array(op_array);
  3845. efree_size(op_array, sizeof(zend_op_array));
  3846. } else {
  3847. if (EG(exception)) {
  3848. zend_exception_error(EG(exception), E_ERROR);
  3849. }
  3850. CG(unclean_shutdown) = 1;
  3851. ret = FAILURE;
  3852. }
  3853. } zend_catch {
  3854. ret = FAILURE;
  3855. } zend_end_try();
  3856. PG(open_basedir) = orig_open_basedir;
  3857. accelerator_orig_compile_file = preload_orig_compile_file;
  3858. ZCG(enabled) = 1;
  3859. zend_destroy_file_handle(&file_handle);
  3860. if (ret == SUCCESS) {
  3861. zend_persistent_script *script;
  3862. int ping_auto_globals_mask;
  3863. int i;
  3864. if (PG(auto_globals_jit)) {
  3865. ping_auto_globals_mask = zend_accel_get_auto_globals();
  3866. }
  3867. if (EG(zend_constants)) {
  3868. /* Remember __COMPILER_HALT_OFFSET__(s). Do this early,
  3869. * as zend_shutdown_executor_values() destroys constants. */
  3870. ZEND_HASH_FOREACH_PTR(preload_scripts, script) {
  3871. zend_execute_data *orig_execute_data = EG(current_execute_data);
  3872. zend_execute_data fake_execute_data;
  3873. zval *offset;
  3874. memset(&fake_execute_data, 0, sizeof(fake_execute_data));
  3875. fake_execute_data.func = (zend_function*)&script->script.main_op_array;
  3876. EG(current_execute_data) = &fake_execute_data;
  3877. if ((offset = zend_get_constant_str("__COMPILER_HALT_OFFSET__", sizeof("__COMPILER_HALT_OFFSET__") - 1)) != NULL) {
  3878. script->compiler_halt_offset = Z_LVAL_P(offset);
  3879. }
  3880. EG(current_execute_data) = orig_execute_data;
  3881. } ZEND_HASH_FOREACH_END();
  3882. }
  3883. /* Cleanup executor */
  3884. EG(flags) |= EG_FLAGS_IN_SHUTDOWN;
  3885. php_call_shutdown_functions();
  3886. zend_call_destructors();
  3887. php_output_end_all();
  3888. php_free_shutdown_functions();
  3889. /* Release stored values to avoid dangling pointers */
  3890. zend_shutdown_executor_values(/* fast_shutdown */ false);
  3891. /* We don't want to preload constants.
  3892. * Check that zend_shutdown_executor_values() also destroys constants. */
  3893. ZEND_ASSERT(zend_hash_num_elements(EG(zend_constants)) == EG(persistent_constants_count));
  3894. zend_hash_init(&EG(symbol_table), 0, NULL, ZVAL_PTR_DTOR, 0);
  3895. CG(map_ptr_last) = orig_map_ptr_last;
  3896. if (EG(full_tables_cleanup)) {
  3897. zend_accel_error_noreturn(ACCEL_LOG_FATAL, "Preloading is not compatible with dl() function.");
  3898. ret = FAILURE;
  3899. goto finish;
  3900. }
  3901. /* Inheritance errors may be thrown during linking */
  3902. zend_try {
  3903. preload_link();
  3904. } zend_catch {
  3905. CG(map_ptr_last) = orig_map_ptr_last;
  3906. ret = FAILURE;
  3907. goto finish;
  3908. } zend_end_try();
  3909. preload_remove_empty_includes();
  3910. script = create_persistent_script();
  3911. script->ping_auto_globals_mask = ping_auto_globals_mask;
  3912. /* Store all functions and classes in a single pseudo-file */
  3913. CG(compiled_filename) = zend_string_init("$PRELOAD$", sizeof("$PRELOAD$") - 1, 0);
  3914. #if ZEND_USE_ABS_CONST_ADDR
  3915. init_op_array(&script->script.main_op_array, ZEND_USER_FUNCTION, 1);
  3916. #else
  3917. init_op_array(&script->script.main_op_array, ZEND_USER_FUNCTION, 2);
  3918. #endif
  3919. script->script.main_op_array.fn_flags |= ZEND_ACC_DONE_PASS_TWO;
  3920. script->script.main_op_array.last = 1;
  3921. script->script.main_op_array.last_literal = 1;
  3922. #if ZEND_USE_ABS_CONST_ADDR
  3923. script->script.main_op_array.literals = (zval*)emalloc(sizeof(zval));
  3924. #else
  3925. script->script.main_op_array.literals = (zval*)(script->script.main_op_array.opcodes + 1);
  3926. #endif
  3927. ZVAL_NULL(script->script.main_op_array.literals);
  3928. memset(script->script.main_op_array.opcodes, 0, sizeof(zend_op));
  3929. script->script.main_op_array.opcodes[0].opcode = ZEND_RETURN;
  3930. script->script.main_op_array.opcodes[0].op1_type = IS_CONST;
  3931. script->script.main_op_array.opcodes[0].op1.constant = 0;
  3932. ZEND_PASS_TWO_UPDATE_CONSTANT(&script->script.main_op_array, script->script.main_op_array.opcodes, script->script.main_op_array.opcodes[0].op1);
  3933. zend_vm_set_opcode_handler(script->script.main_op_array.opcodes);
  3934. script->script.filename = CG(compiled_filename);
  3935. CG(compiled_filename) = NULL;
  3936. script->script.first_early_binding_opline = (uint32_t)-1;
  3937. preload_move_user_functions(CG(function_table), &script->script.function_table);
  3938. preload_move_user_classes(CG(class_table), &script->script.class_table);
  3939. zend_hash_sort_ex(&script->script.class_table, preload_sort_classes, NULL, 0);
  3940. if (preload_optimize(script) != SUCCESS) {
  3941. zend_accel_error_noreturn(ACCEL_LOG_FATAL, "Optimization error during preloading!");
  3942. return FAILURE;
  3943. }
  3944. zend_shared_alloc_init_xlat_table();
  3945. HANDLE_BLOCK_INTERRUPTIONS();
  3946. SHM_UNPROTECT();
  3947. ZCSG(preload_script) = preload_script_in_shared_memory(script);
  3948. SHM_PROTECT();
  3949. HANDLE_UNBLOCK_INTERRUPTIONS();
  3950. preload_load();
  3951. /* Store individual scripts with unlinked classes */
  3952. HANDLE_BLOCK_INTERRUPTIONS();
  3953. SHM_UNPROTECT();
  3954. i = 0;
  3955. ZCSG(saved_scripts) = zend_shared_alloc((zend_hash_num_elements(preload_scripts) + 1) * sizeof(void*));
  3956. ZEND_HASH_FOREACH_PTR(preload_scripts, script) {
  3957. if (zend_hash_num_elements(&script->script.class_table) > 1) {
  3958. zend_hash_sort_ex(&script->script.class_table, preload_sort_classes, NULL, 0);
  3959. }
  3960. ZCSG(saved_scripts)[i++] = preload_script_in_shared_memory(script);
  3961. } ZEND_HASH_FOREACH_END();
  3962. ZCSG(saved_scripts)[i] = NULL;
  3963. zend_shared_alloc_save_state();
  3964. accel_interned_strings_save_state();
  3965. SHM_PROTECT();
  3966. HANDLE_UNBLOCK_INTERRUPTIONS();
  3967. zend_shared_alloc_destroy_xlat_table();
  3968. } else {
  3969. CG(map_ptr_last) = orig_map_ptr_last;
  3970. }
  3971. finish:
  3972. CG(compiler_options) = orig_compiler_options;
  3973. zend_hash_destroy(preload_scripts);
  3974. efree(preload_scripts);
  3975. preload_scripts = NULL;
  3976. return ret;
  3977. }
  3978. static size_t preload_ub_write(const char *str, size_t str_length)
  3979. {
  3980. return fwrite(str, 1, str_length, stdout);
  3981. }
  3982. static void preload_flush(void *server_context)
  3983. {
  3984. fflush(stdout);
  3985. }
  3986. static int preload_header_handler(sapi_header_struct *h, sapi_header_op_enum op, sapi_headers_struct *s)
  3987. {
  3988. return 0;
  3989. }
  3990. static int preload_send_headers(sapi_headers_struct *sapi_headers)
  3991. {
  3992. return SAPI_HEADER_SENT_SUCCESSFULLY;
  3993. }
  3994. static void preload_send_header(sapi_header_struct *sapi_header, void *server_context)
  3995. {
  3996. }
  3997. static int accel_finish_startup(void)
  3998. {
  3999. if (!ZCG(enabled) || !accel_startup_ok) {
  4000. return SUCCESS;
  4001. }
  4002. if (ZCG(accel_directives).preload && *ZCG(accel_directives).preload) {
  4003. #ifdef ZEND_WIN32
  4004. zend_accel_error_noreturn(ACCEL_LOG_ERROR, "Preloading is not supported on Windows");
  4005. return FAILURE;
  4006. #else
  4007. int in_child = 0;
  4008. int ret = SUCCESS;
  4009. int rc;
  4010. int orig_error_reporting;
  4011. int (*orig_activate)(void) = sapi_module.activate;
  4012. int (*orig_deactivate)(void) = sapi_module.deactivate;
  4013. void (*orig_register_server_variables)(zval *track_vars_array) = sapi_module.register_server_variables;
  4014. int (*orig_header_handler)(sapi_header_struct *sapi_header, sapi_header_op_enum op, sapi_headers_struct *sapi_headers) = sapi_module.header_handler;
  4015. int (*orig_send_headers)(sapi_headers_struct *sapi_headers) = sapi_module.send_headers;
  4016. void (*orig_send_header)(sapi_header_struct *sapi_header, void *server_context)= sapi_module.send_header;
  4017. char *(*orig_getenv)(const char *name, size_t name_len) = sapi_module.getenv;
  4018. size_t (*orig_ub_write)(const char *str, size_t str_length) = sapi_module.ub_write;
  4019. void (*orig_flush)(void *server_context) = sapi_module.flush;
  4020. #ifdef ZEND_SIGNALS
  4021. bool old_reset_signals = SIGG(reset);
  4022. #endif
  4023. if (UNEXPECTED(file_cache_only)) {
  4024. zend_accel_error(ACCEL_LOG_WARNING, "Preloading doesn't work in \"file_cache_only\" mode");
  4025. return SUCCESS;
  4026. }
  4027. /* exclusive lock */
  4028. zend_shared_alloc_lock();
  4029. if (ZCSG(preload_script)) {
  4030. /* Preloading was done in another process */
  4031. preload_load();
  4032. zend_shared_alloc_unlock();
  4033. return SUCCESS;
  4034. }
  4035. if (geteuid() == 0) {
  4036. pid_t pid;
  4037. struct passwd *pw;
  4038. if (!ZCG(accel_directives).preload_user
  4039. || !*ZCG(accel_directives).preload_user) {
  4040. zend_shared_alloc_unlock();
  4041. zend_accel_error_noreturn(ACCEL_LOG_FATAL, "\"opcache.preload_user\" has not been defined");
  4042. return FAILURE;
  4043. }
  4044. pw = getpwnam(ZCG(accel_directives).preload_user);
  4045. if (pw == NULL) {
  4046. zend_shared_alloc_unlock();
  4047. zend_accel_error_noreturn(ACCEL_LOG_FATAL, "Preloading failed to getpwnam(\"%s\")", ZCG(accel_directives).preload_user);
  4048. return FAILURE;
  4049. }
  4050. pid = fork();
  4051. if (pid == -1) {
  4052. zend_shared_alloc_unlock();
  4053. zend_accel_error_noreturn(ACCEL_LOG_FATAL, "Preloading failed to fork()");
  4054. return FAILURE;
  4055. } else if (pid == 0) { /* children */
  4056. if (setgid(pw->pw_gid) < 0) {
  4057. zend_accel_error(ACCEL_LOG_WARNING, "Preloading failed to setgid(%d)", pw->pw_gid);
  4058. exit(1);
  4059. }
  4060. if (initgroups(pw->pw_name, pw->pw_gid) < 0) {
  4061. zend_accel_error(ACCEL_LOG_WARNING, "Preloading failed to initgroups(\"%s\", %d)", pw->pw_name, pw->pw_uid);
  4062. exit(1);
  4063. }
  4064. if (setuid(pw->pw_uid) < 0) {
  4065. zend_accel_error(ACCEL_LOG_WARNING, "Preloading failed to setuid(%d)", pw->pw_uid);
  4066. exit(1);
  4067. }
  4068. in_child = 1;
  4069. } else { /* parent */
  4070. int status;
  4071. if (waitpid(pid, &status, 0) < 0) {
  4072. zend_shared_alloc_unlock();
  4073. zend_accel_error_noreturn(ACCEL_LOG_FATAL, "Preloading failed to waitpid(%d)", pid);
  4074. return FAILURE;
  4075. }
  4076. if (ZCSG(preload_script)) {
  4077. preload_load();
  4078. }
  4079. zend_shared_alloc_unlock();
  4080. if (WIFEXITED(status) && WEXITSTATUS(status) == 0) {
  4081. return SUCCESS;
  4082. } else {
  4083. return FAILURE;
  4084. }
  4085. }
  4086. } else {
  4087. if (ZCG(accel_directives).preload_user
  4088. && *ZCG(accel_directives).preload_user) {
  4089. zend_accel_error(ACCEL_LOG_WARNING, "\"opcache.preload_user\" is ignored");
  4090. }
  4091. }
  4092. sapi_module.activate = NULL;
  4093. sapi_module.deactivate = NULL;
  4094. sapi_module.register_server_variables = NULL;
  4095. sapi_module.header_handler = preload_header_handler;
  4096. sapi_module.send_headers = preload_send_headers;
  4097. sapi_module.send_header = preload_send_header;
  4098. sapi_module.getenv = NULL;
  4099. sapi_module.ub_write = preload_ub_write;
  4100. sapi_module.flush = preload_flush;
  4101. zend_interned_strings_switch_storage(1);
  4102. #ifdef ZEND_SIGNALS
  4103. SIGG(reset) = 0;
  4104. #endif
  4105. orig_error_reporting = EG(error_reporting);
  4106. EG(error_reporting) = 0;
  4107. rc = php_request_startup();
  4108. EG(error_reporting) = orig_error_reporting;
  4109. if (rc == SUCCESS) {
  4110. bool orig_report_memleaks;
  4111. /* don't send headers */
  4112. SG(headers_sent) = 1;
  4113. SG(request_info).no_headers = 1;
  4114. php_output_set_status(0);
  4115. ZCG(auto_globals_mask) = 0;
  4116. ZCG(request_time) = (time_t)sapi_get_request_time();
  4117. ZCG(cache_opline) = NULL;
  4118. ZCG(cache_persistent_script) = NULL;
  4119. ZCG(include_path_key_len) = 0;
  4120. ZCG(include_path_check) = 1;
  4121. ZCG(cwd) = NULL;
  4122. ZCG(cwd_key_len) = 0;
  4123. ZCG(cwd_check) = 1;
  4124. if (accel_preload(ZCG(accel_directives).preload, in_child) != SUCCESS) {
  4125. ret = FAILURE;
  4126. }
  4127. preload_flush(NULL);
  4128. orig_report_memleaks = PG(report_memleaks);
  4129. PG(report_memleaks) = 0;
  4130. #ifdef ZEND_SIGNALS
  4131. /* We may not have registered signal handlers due to SIGG(reset)=0, so
  4132. * also disable the check that they are registered. */
  4133. SIGG(check) = 0;
  4134. #endif
  4135. php_request_shutdown(NULL); /* calls zend_shared_alloc_unlock(); */
  4136. PG(report_memleaks) = orig_report_memleaks;
  4137. } else {
  4138. zend_shared_alloc_unlock();
  4139. ret = FAILURE;
  4140. }
  4141. #ifdef ZEND_SIGNALS
  4142. SIGG(reset) = old_reset_signals;
  4143. #endif
  4144. sapi_module.activate = orig_activate;
  4145. sapi_module.deactivate = orig_deactivate;
  4146. sapi_module.register_server_variables = orig_register_server_variables;
  4147. sapi_module.header_handler = orig_header_handler;
  4148. sapi_module.send_headers = orig_send_headers;
  4149. sapi_module.send_header = orig_send_header;
  4150. sapi_module.getenv = orig_getenv;
  4151. sapi_module.ub_write = orig_ub_write;
  4152. sapi_module.flush = orig_flush;
  4153. sapi_activate();
  4154. if (in_child) {
  4155. if (ret == SUCCESS) {
  4156. exit(0);
  4157. } else {
  4158. exit(2);
  4159. }
  4160. }
  4161. return ret;
  4162. #endif
  4163. }
  4164. return SUCCESS;
  4165. }
  4166. ZEND_EXT_API zend_extension zend_extension_entry = {
  4167. ACCELERATOR_PRODUCT_NAME, /* name */
  4168. PHP_VERSION, /* version */
  4169. "Zend Technologies", /* author */
  4170. "http://www.zend.com/", /* URL */
  4171. "Copyright (c)", /* copyright */
  4172. accel_startup, /* startup */
  4173. NULL, /* shutdown */
  4174. NULL, /* per-script activation */
  4175. #ifdef HAVE_JIT
  4176. accel_deactivate, /* per-script deactivation */
  4177. #else
  4178. NULL, /* per-script deactivation */
  4179. #endif
  4180. NULL, /* message handler */
  4181. NULL, /* op_array handler */
  4182. NULL, /* extended statement handler */
  4183. NULL, /* extended fcall begin handler */
  4184. NULL, /* extended fcall end handler */
  4185. NULL, /* op_array ctor */
  4186. NULL, /* op_array dtor */
  4187. STANDARD_ZEND_EXTENSION_PROPERTIES
  4188. };