ZendAccelerator.c 142 KB

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