source: trunk/xcache.c @ 1134

Last change on this file since 1134 was 1134, checked in by moo, 2 years ago

refactor: fix build for previous code clean up

  • Property svn:eol-style set to native
File size: 21.6 KB
RevLine 
[1]1/* {{{ macros */
2#include <stdlib.h>
3#include <stdio.h>
4#include <string.h>
5
6#include <signal.h>
7
8#include "xcache.h"
[993]9
10#ifdef HAVE_XCACHE_OPTIMIZER
[1003]11#   include "mod_optimizer/xc_optimizer.h"
[993]12#endif
[1040]13#ifdef HAVE_XCACHE_CACHER
14#   include "mod_cacher/xc_cacher.h"
15#endif
[993]16#ifdef HAVE_XCACHE_COVERAGER
[1003]17#   include "mod_coverager/xc_coverager.h"
[993]18#endif
19#ifdef HAVE_XCACHE_DISASSEMBLER
[1003]20#   include "mod_disassembler/xc_disassembler.h"
[993]21#endif
22
[1]23#include "xcache_globals.h"
[1026]24#include "xcache/xc_extension.h"
25#include "xcache/xc_ini.h"
[987]26#include "xcache/xc_const_string.h"
27#include "xcache/xc_opcode_spec.h"
28#include "xcache/xc_utils.h"
[982]29#include "util/xc_stack.h"
[1]30
[1026]31#include "php.h"
32#include "ext/standard/info.h"
33#include "ext/standard/php_string.h"
[1131]34#include "SAPI.h"
[1]35/* }}} */
36
37/* {{{ globals */
38static char *xc_coredump_dir = NULL;
[979]39static zend_bool xc_disable_on_crash = 0;
[1]40
[403]41static zend_compile_file_t *old_compile_file = NULL;
[1]42
[1040]43zend_bool xc_test = 0;
[1]44
[982]45ZEND_DECLARE_MODULE_GLOBALS(xcache)
[854]46
[1]47/* }}} */
48
[405]49static zend_op_array *xc_check_initial_compile_file(zend_file_handle *h, int type TSRMLS_DC) /* {{{ */
50{
51    XG(initial_compile_file_called) = 1;
[1040]52    return old_compile_file(h, type TSRMLS_CC);
[405]53}
54/* }}} */
[937]55
[1]56/* module helper function */
57static int xc_init_constant(int module_number TSRMLS_DC) /* {{{ */
58{
[11]59    typedef struct {
[1]60        const char *prefix;
[20]61        zend_uchar (*getsize)();
[1]62        const char *(*get)(zend_uchar i);
[1133]63    } xc_nameinfo_t;
64    xc_nameinfo_t nameinfos[] = {
[1]65        { "",        xc_get_op_type_count,   xc_get_op_type   },
66        { "",        xc_get_data_type_count, xc_get_data_type },
67        { "",        xc_get_opcode_count,    xc_get_opcode    },
68        { "OPSPEC_", xc_get_op_spec_count,   xc_get_op_spec   },
69        { NULL, NULL, NULL }
70    };
71    int undefdone = 0;
[1134]72    xc_nameinfo_t *p;
[1]73
74    for (p = nameinfos; p->getsize; p ++) {
[1133]75        zend_uchar i, count;
76        char const_name[96];
77        int const_name_len;
78
[20]79        count = p->getsize();
80        for (i = 0; i < count; i ++) {
[1]81            const char *name = p->get(i);
82            if (!name) continue;
83            if (strcmp(name, "UNDEF") == 0) {
84                if (undefdone) continue;
85                undefdone = 1;
86            }
87            const_name_len = snprintf(const_name, sizeof(const_name), "XC_%s%s", p->prefix, name);
88            zend_register_long_constant(const_name, const_name_len+1, i, CONST_CS | CONST_PERSISTENT, module_number TSRMLS_CC);
89        }
90    }
91
92    zend_register_long_constant(ZEND_STRS("XC_SIZEOF_TEMP_VARIABLE"), sizeof(temp_variable), CONST_CS | CONST_PERSISTENT, module_number TSRMLS_CC);
[119]93    zend_register_stringl_constant(ZEND_STRS("XCACHE_VERSION"), ZEND_STRL(XCACHE_VERSION), CONST_CS | CONST_PERSISTENT, module_number TSRMLS_CC);
94    zend_register_stringl_constant(ZEND_STRS("XCACHE_MODULES"), ZEND_STRL(XCACHE_MODULES), CONST_CS | CONST_PERSISTENT, module_number TSRMLS_CC);
[1]95    return 0;
96}
97/* }}} */
[92]98/* {{{ PHP_GINIT_FUNCTION(xcache) */
[1050]99#pragma GCC push_options
100#pragma GCC diagnostic ignored "-Wshadow"
101
[92]102#ifdef PHP_GINIT_FUNCTION
[1050]103static PHP_GINIT_FUNCTION(xcache)
[92]104#else
[1050]105static void xc_init_globals(zend_xcache_globals* xcache_globals TSRMLS_DC)
[92]106#endif
[1]107{
[1050]108#pragma GCC pop_options
109
[92]110    memset(xcache_globals, 0, sizeof(zend_xcache_globals));
[429]111
[588]112#ifdef HAVE_XCACHE_CONSTANT
[640]113    zend_hash_init_ex(&xcache_globals->internal_constant_table, 1, NULL, (dtor_func_t) xc_zend_constant_dtor, 1, 0);
[588]114#endif
[429]115    zend_hash_init_ex(&xcache_globals->internal_function_table, 1, NULL, NULL, 1, 0);
116    zend_hash_init_ex(&xcache_globals->internal_class_table,    1, NULL, NULL, 1, 0);
[1]117}
118/* }}} */
[92]119/* {{{ PHP_GSHUTDOWN_FUNCTION(xcache) */
120static
121#ifdef PHP_GSHUTDOWN_FUNCTION
122PHP_GSHUTDOWN_FUNCTION(xcache)
123#else
124void xc_shutdown_globals(zend_xcache_globals* xcache_globals TSRMLS_DC)
125#endif
[1]126{
[917]127    size_t i;
[1]128
[92]129    if (xcache_globals->php_holds != NULL) {
[1040]130        for (i = 0; i < xcache_globals->php_holds_size; i ++) {
[92]131            xc_stack_destroy(&xcache_globals->php_holds[i]);
[1]132        }
[92]133        free(xcache_globals->php_holds);
134        xcache_globals->php_holds = NULL;
[1040]135        xcache_globals->php_holds_size = 0;
[1]136    }
137
[92]138    if (xcache_globals->var_holds != NULL) {
[1040]139        for (i = 0; i < xcache_globals->var_holds_size; i ++) {
[92]140            xc_stack_destroy(&xcache_globals->var_holds[i]);
[1]141        }
[92]142        free(xcache_globals->var_holds);
143        xcache_globals->var_holds = NULL;
[1040]144        xcache_globals->var_holds_size = 0;
[1]145    }
[344]146
[438]147    if (xcache_globals->internal_table_copied) {
[588]148#ifdef HAVE_XCACHE_CONSTANT
149        zend_hash_destroy(&xcache_globals->internal_constant_table);
150#endif
[435]151        zend_hash_destroy(&xcache_globals->internal_function_table);
152        zend_hash_destroy(&xcache_globals->internal_class_table);
153    }
[1]154}
155/* }}} */
156
[780]157/* {{{ proto int xcache_get_refcount(mixed variable)
[781]158   XCache internal uses only: Get reference count of variable */
[780]159PHP_FUNCTION(xcache_get_refcount)
160{
161    zval *variable;
162    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &variable) == FAILURE) {
163        RETURN_NULL();
164    }
165
[798]166    RETURN_LONG(Z_REFCOUNT(*variable));
[780]167}
168/* }}} */
169/* {{{ proto bool xcache_get_isref(mixed variable)
[781]170   XCache internal uses only: Check if variable data is marked referenced */
[1027]171#ifdef ZEND_BEGIN_ARG_INFO_EX
[781]172ZEND_BEGIN_ARG_INFO_EX(arginfo_xcache_get_isref, 0, 0, 1)
173    ZEND_ARG_INFO(1, variable)
174ZEND_END_ARG_INFO()
[1027]175#else
176static unsigned char arginfo_xcache_get_isref[] = { 1, BYREF_FORCE };
177#endif
[781]178
[780]179PHP_FUNCTION(xcache_get_isref)
180{
181    zval *variable;
182    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &variable) == FAILURE) {
183        RETURN_NULL();
184    }
185
[798]186    RETURN_BOOL(Z_ISREF(*variable) && Z_REFCOUNT(*variable) >= 3);
[780]187}
188/* }}} */
[532]189#ifdef HAVE_XCACHE_DPRINT
190/* {{{ proto bool  xcache_dprint(mixed value)
191   Prints variable (or value) internal struct (debug only) */
192PHP_FUNCTION(xcache_dprint)
193{
194    zval *value;
195
196    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &value) == FAILURE) {
197        return;
198    }
199    xc_dprint_zval(value, 0 TSRMLS_CC);
200}
201/* }}} */
202#endif
[9]203/* {{{ proto string xcache_asm(string filename)
204 */
[1]205#ifdef HAVE_XCACHE_ASSEMBLER
206PHP_FUNCTION(xcache_asm)
207{
208}
209#endif
210/* }}} */
[9]211/* {{{ proto string xcache_encode(string filename)
212   Encode php file into XCache opcode encoded format */
[1]213#ifdef HAVE_XCACHE_ENCODER
214PHP_FUNCTION(xcache_encode)
215{
216}
217#endif
218/* }}} */
[9]219/* {{{ proto bool xcache_decode_file(string filename)
220   Decode(load) opcode from XCache encoded format file */
[1]221#ifdef HAVE_XCACHE_DECODER
[9]222PHP_FUNCTION(xcache_decode_file)
[1]223{
224}
225#endif
226/* }}} */
[9]227/* {{{ proto bool xcache_decode_string(string data)
228   Decode(load) opcode from XCache encoded format data */
229#ifdef HAVE_XCACHE_DECODER
230PHP_FUNCTION(xcache_decode_string)
231{
232}
233#endif
234/* }}} */
[1]235/* {{{ xc_call_getter */
236typedef const char *(xc_name_getter_t)(zend_uchar type);
237static void xc_call_getter(xc_name_getter_t getter, int count, INTERNAL_FUNCTION_PARAMETERS)
238{
239    long spec;
240    const char *name;
241
242    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &spec) == FAILURE) {
243        return;
244    }
245    if (spec >= 0 && spec < count) {
[11]246        name = getter((zend_uchar) spec);
[1]247        if (name) {
248            /* RETURN_STRING */
249            int len = strlen(name);
250            return_value->value.str.len = len;
251            return_value->value.str.val = estrndup(name, len);
252            return_value->type = IS_STRING; 
253            return;
254        }
255    }
256    RETURN_NULL();
257}
258/* }}} */
259/* {{{ proto string xcache_get_op_type(int op_type) */
260PHP_FUNCTION(xcache_get_op_type)
261{
262    xc_call_getter(xc_get_op_type, xc_get_op_type_count(), INTERNAL_FUNCTION_PARAM_PASSTHRU);
263}
264/* }}} */
265/* {{{ proto string xcache_get_data_type(int type) */
266PHP_FUNCTION(xcache_get_data_type)
267{
268    xc_call_getter(xc_get_data_type, xc_get_data_type_count(), INTERNAL_FUNCTION_PARAM_PASSTHRU);
269}
270/* }}} */
271/* {{{ proto string xcache_get_opcode(int opcode) */
272PHP_FUNCTION(xcache_get_opcode)
273{
274    xc_call_getter(xc_get_opcode, xc_get_opcode_count(), INTERNAL_FUNCTION_PARAM_PASSTHRU);
275}
276/* }}} */
277/* {{{ proto string xcache_get_op_spec(int op_type) */
278PHP_FUNCTION(xcache_get_op_spec)
279{
280    xc_call_getter(xc_get_op_spec, xc_get_op_spec_count(), INTERNAL_FUNCTION_PARAM_PASSTHRU);
281}
282/* }}} */
283/* {{{ proto string xcache_get_opcode_spec(int opcode) */
284PHP_FUNCTION(xcache_get_opcode_spec)
285{
286    long spec;
287    const xc_opcode_spec_t *opspec;
288
289    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &spec) == FAILURE) {
290        return;
291    }
[17]292    if ((zend_uchar) spec <= xc_get_opcode_spec_count()) {
[11]293        opspec = xc_get_opcode_spec((zend_uchar) spec);
[1]294        if (opspec) {
295            array_init(return_value);
296            add_assoc_long_ex(return_value, ZEND_STRS("ext"), opspec->ext);
297            add_assoc_long_ex(return_value, ZEND_STRS("op1"), opspec->op1);
298            add_assoc_long_ex(return_value, ZEND_STRS("op2"), opspec->op2);
299            add_assoc_long_ex(return_value, ZEND_STRS("res"), opspec->res);
300            return;
301        }
302    }
303    RETURN_NULL();
304}
305/* }}} */
[781]306/* {{{ proto mixed xcache_get_special_value(zval value)
307   XCache internal use only: For decompiler to get static value with type fixed */
[1]308PHP_FUNCTION(xcache_get_special_value)
309{
310    zval *value;
311
312    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &value) == FAILURE) {
313        return;
314    }
315
[713]316    switch ((Z_TYPE_P(value) & IS_CONSTANT_TYPE_MASK)) {
317    case IS_CONSTANT:
[1]318        *return_value = *value;
319        zval_copy_ctor(return_value);
320        return_value->type = UNISW(IS_STRING, UG(unicode) ? IS_UNICODE : IS_STRING);
[713]321        break;
[1]322
[713]323    case IS_CONSTANT_ARRAY:
[1]324        *return_value = *value;
325        zval_copy_ctor(return_value);
326        return_value->type = IS_ARRAY;
[713]327        break;
328
329    default:
330        RETURN_NULL();
[1]331    }
332}
333/* }}} */
[781]334/* {{{ proto int xcache_get_type(zval value)
335   XCache internal use only for disassembler to get variable type in engine level */
336PHP_FUNCTION(xcache_get_type)
337{
338    zval *value;
339
340    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &value) == FAILURE) {
341        return;
342    }
343
344    RETURN_LONG(Z_TYPE_P(value));
345}
346/* }}} */
[1]347/* {{{ proto string xcache_coredump(int op_type) */
348PHP_FUNCTION(xcache_coredump)
349{
[9]350    if (xc_test) {
351        raise(SIGSEGV);
352    }
353    else {
354        php_error_docref(NULL TSRMLS_CC, E_WARNING, "xcache.test must be enabled to test xcache_coredump()");
355    }
[1]356}
357/* }}} */
358/* {{{ proto string xcache_is_autoglobal(string name) */
359PHP_FUNCTION(xcache_is_autoglobal)
360{
[860]361    zval *name;
[1]362
[862]363    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &name) == FAILURE) {
[1]364        return;
365    }
366
[862]367#ifdef IS_UNICODE
368    convert_to_unicode(name);
369#else
370    convert_to_string(name);
371#endif
372
[860]373    RETURN_BOOL(zend_u_hash_exists(CG(auto_globals), UG(unicode), Z_STRVAL_P(name), Z_STRLEN_P(name) + 1));
[1]374}
375/* }}} */
[716]376static zend_function_entry xcache_functions[] = /* {{{ */
[1]377{
378    PHP_FE(xcache_coredump,          NULL)
379#ifdef HAVE_XCACHE_ASSEMBLER
380    PHP_FE(xcache_asm,               NULL)
381#endif
382#ifdef HAVE_XCACHE_ENCODER
383    PHP_FE(xcache_encode,            NULL)
384#endif
385#ifdef HAVE_XCACHE_DECODER
[9]386    PHP_FE(xcache_decode_file,       NULL)
387    PHP_FE(xcache_decode_string,     NULL)
[1]388#endif
389    PHP_FE(xcache_get_special_value, NULL)
[781]390    PHP_FE(xcache_get_type,          NULL)
[1]391    PHP_FE(xcache_get_op_type,       NULL)
392    PHP_FE(xcache_get_data_type,     NULL)
393    PHP_FE(xcache_get_opcode,        NULL)
394    PHP_FE(xcache_get_opcode_spec,   NULL)
395    PHP_FE(xcache_is_autoglobal,     NULL)
[780]396    PHP_FE(xcache_get_refcount,      NULL)
[781]397    PHP_FE(xcache_get_isref,         arginfo_xcache_get_isref)
[532]398#ifdef HAVE_XCACHE_DPRINT
399    PHP_FE(xcache_dprint,            NULL)
400#endif
[983]401    PHP_FE_END
[1]402};
403/* }}} */
404
[914]405#ifdef ZEND_WIN32
406#include "dbghelp.h"
407typedef BOOL (WINAPI *MINIDUMPWRITEDUMP)(HANDLE hProcess, DWORD dwPid, HANDLE hFile, MINIDUMP_TYPE DumpType,
408        CONST PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam,
409        CONST PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam,
410        CONST PMINIDUMP_CALLBACK_INFORMATION CallbackParam
411        );
412
[915]413static PTOP_LEVEL_EXCEPTION_FILTER oldFilter = NULL;
[914]414static HMODULE dbghelpModule = NULL;
[915]415static char crash_dumpPath[_MAX_PATH] = { 0 };
416static MINIDUMPWRITEDUMP dbghelp_MiniDumpWriteDump = NULL;
[914]417
418static LONG WINAPI miniDumperFilter(struct _EXCEPTION_POINTERS *pExceptionInfo) /* {{{ */
419{
420    HANDLE fileHandle;
[1106]421    LONG ret = EXCEPTION_CONTINUE_SEARCH;
[914]422
423    SetUnhandledExceptionFilter(oldFilter);
424
425    /* create the file */
426    fileHandle = CreateFile(crash_dumpPath, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
427
428    if (fileHandle != INVALID_HANDLE_VALUE) {
429        MINIDUMP_EXCEPTION_INFORMATION exceptionInformation;
430        BOOL ok;
431
432        exceptionInformation.ThreadId = GetCurrentThreadId();
433        exceptionInformation.ExceptionPointers = pExceptionInfo;
434        exceptionInformation.ClientPointers = FALSE;
435
436        /* write the dump */
[925]437        ok = dbghelp_MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(), fileHandle, MiniDumpNormal|MiniDumpWithDataSegs|MiniDumpWithIndirectlyReferencedMemory, &exceptionInformation, NULL, NULL);
[914]438        CloseHandle(fileHandle);
439        if (ok) {
440            zend_error(E_ERROR, "Saved dump file to '%s'", crash_dumpPath);
[1106]441            ret = EXCEPTION_EXECUTE_HANDLER;
[914]442        }
443        else {
444            zend_error(E_ERROR, "Failed to save dump file to '%s' (error %d)", crash_dumpPath, GetLastError());
445        }
446    }
447    else {
448        zend_error(E_ERROR, "Failed to create dump file '%s' (error %d)", crash_dumpPath, GetLastError());
449    }
450
[1106]451    if (xc_disable_on_crash) {
452        xc_disable_on_crash = 0;
453        xc_cacher_disable();
454    }
455
456    return ret;
[914]457}
458/* }}} */
459
460static void xcache_restore_crash_handler() /* {{{ */
461{
462    if (oldFilter) {
463        SetUnhandledExceptionFilter(oldFilter);
464        oldFilter = NULL;
465    }
466}
467/* }}} */
468static void xcache_init_crash_handler() /* {{{ */
469{
470    /* firstly see if dbghelp.dll is around and has the function we need
471       look next to the EXE first, as the one in System32 might be old
472       (e.g. Windows 2000) */
473    char dbghelpPath[_MAX_PATH];
474
475    if (GetModuleFileName(NULL, dbghelpPath, _MAX_PATH)) {
476        char *slash = strchr(dbghelpPath, '\\');
477        if (slash) {
478            strcpy(slash + 1, "DBGHELP.DLL");
479            dbghelpModule = LoadLibrary(dbghelpPath);
480        }
481    }
482
483    if (!dbghelpModule) {
484        /* load any version we can */
485        dbghelpModule = LoadLibrary("DBGHELP.DLL");
486        if (!dbghelpModule) {
487            zend_error(E_ERROR, "Unable to enable crash dump saver: %s", "DBGHELP.DLL not found");
488            return;
489        }
490    }
491
492    dbghelp_MiniDumpWriteDump = (MINIDUMPWRITEDUMP)GetProcAddress(dbghelpModule, "MiniDumpWriteDump");
[918]493    if (!dbghelp_MiniDumpWriteDump) {
494        zend_error(E_ERROR, "Unable to enable crash dump saver: %s", "DBGHELP.DLL too old. Get updated dll and put it aside of php_xcache.dll");
[914]495        return;
496    }
497
[923]498#ifdef XCACHE_VERSION_REVISION
499#define REVISION "r" XCACHE_VERSION_REVISION
500#else
501#define REVISION ""
502#endif
[925]503    sprintf(crash_dumpPath, "%s\\php-%s-xcache-%s%s-%lu-%lu.dmp", xc_coredump_dir, zend_get_module_version("standard"), XCACHE_VERSION, REVISION, (unsigned long) time(NULL), (unsigned long) GetCurrentProcessId());
[923]504#undef REVISION
[914]505
506    oldFilter = SetUnhandledExceptionFilter(&miniDumperFilter);
507}
508/* }}} */
509#else
[75]510/* old signal handlers {{{ */
511typedef void (*xc_sighandler_t)(int);
512#define FOREACH_SIG(sig) static xc_sighandler_t old_##sig##_handler = NULL
[982]513#include "util/xc_foreachcoresig.h"
[75]514#undef FOREACH_SIG
515/* }}} */
516static void xcache_signal_handler(int sig);
[914]517static void xcache_restore_crash_handler() /* {{{ */
[1]518{
[75]519#define FOREACH_SIG(sig) do { \
520    if (old_##sig##_handler != xcache_signal_handler) { \
521        signal(sig, old_##sig##_handler); \
522    } \
523    else { \
524        signal(sig, SIG_DFL); \
525    } \
526} while (0)
[982]527#include "util/xc_foreachcoresig.h"
[75]528#undef FOREACH_SIG
529}
530/* }}} */
[914]531static void xcache_init_crash_handler() /* {{{ */
[75]532{
533#define FOREACH_SIG(sig) \
534    old_##sig##_handler = signal(sig, xcache_signal_handler)
[982]535#include "util/xc_foreachcoresig.h"
[75]536#undef FOREACH_SIG
537}
538/* }}} */
539static void xcache_signal_handler(int sig) /* {{{ */
540{
[914]541    xcache_restore_crash_handler();
[1]542    if (xc_coredump_dir && xc_coredump_dir[0]) {
[767]543        if (chdir(xc_coredump_dir) != 0) {
544            /* error, but nothing can do about it
545             * and should'nt print anything which might SEGV again */
546        }
[1]547    }
[979]548    if (xc_disable_on_crash) {
549        xc_disable_on_crash = 0;
[1040]550        xc_cacher_disable();
[979]551    }
[65]552    raise(sig);
[1]553}
554/* }}} */
[914]555#endif
[1]556
[1047]557/* {{{ incompatible zend extensions handling */
558typedef struct {
559    const char *name;
560    startup_func_t old_startup;
561} xc_incompatible_zend_extension_info_t;
562static xc_incompatible_zend_extension_info_t xc_incompatible_zend_extensions[] = {
563    { "Zend Optimizer", NULL }
564};
565
566static xc_incompatible_zend_extension_info_t *xc_get_incompatible_zend_extension_info(const char *name)
[164]567{
[1047]568    size_t i;
569
570    for (i = 0; i < sizeof(xc_incompatible_zend_extensions) / sizeof(xc_incompatible_zend_extensions[0]); ++i) {
571        xc_incompatible_zend_extension_info_t *incompatible_zend_extension_info = &xc_incompatible_zend_extensions[i];
572        if (strcmp(incompatible_zend_extension_info->name, name) == 0) {
573            return incompatible_zend_extension_info;
[1026]574        }
575    }
[1045]576
[1047]577    return NULL;
578}
579/* }}} */
580static int xc_incompatible_zend_extension_startup_hook(zend_extension *extension) /* {{{ */
581{
582    xc_incompatible_zend_extension_info_t *incompatible_zend_extension_info = xc_get_incompatible_zend_extension_info(extension->name);
583    int status;
584    zend_bool catched = 0;
585    zend_llist old_zend_extensions = zend_extensions;
586    TSRMLS_FETCH();
587
588    /* hide all extensions from it */
589    zend_extensions.head = NULL;
590    zend_extensions.count = 0;
591
592    /* restore */
593    extension->startup = incompatible_zend_extension_info->old_startup;
594    incompatible_zend_extension_info->old_startup = NULL;
595    assert(extension->startup);
596
597    zend_try {
598        status = extension->startup(extension);
599    } zend_catch {
600        catched = 1;
601    } zend_end_try();
602
603    zend_extensions = old_zend_extensions;
604    if (catched) {
605        zend_bailout();
[1045]606    }
[1047]607    return status;
[164]608}
[1026]609/* }}} */
610static int xc_zend_startup(zend_extension *extension) /* {{{ */
[164]611{
[1047]612    zend_llist_position lpos;
613    zend_extension *ext;
614
615    ext = (zend_extension *) zend_extensions.head->data;
616    if (strcmp(ext->name, XCACHE_NAME) != 0) {
617        zend_error(E_WARNING, "XCache failed to load itself as the before \"%s\". compatibility downgraded", ext->name);
618    }
619
[1040]620    old_compile_file = zend_compile_file;
[1030]621    zend_compile_file = xc_check_initial_compile_file;
[164]622
[1047]623    for (ext = (zend_extension *) zend_llist_get_first_ex(&zend_extensions, &lpos);
624            ext;
625            ext = (zend_extension *) zend_llist_get_next_ex(&zend_extensions, &lpos)) {
[1061]626        xc_incompatible_zend_extension_info_t *incompatible_zend_extension_info = xc_get_incompatible_zend_extension_info(ext->name);
[1047]627        if (incompatible_zend_extension_info) {
628            assert(!incompatible_zend_extension_info->old_startup);
629            incompatible_zend_extension_info->old_startup = ext->startup;
630            ext->startup = xc_incompatible_zend_extension_startup_hook;
[1026]631        }
[1]632    }
633    return SUCCESS;
634}
[1026]635/* }}} */
636static void xc_zend_shutdown(zend_extension *extension) /* {{{ */
[1]637{
638}
[1026]639/* }}} */
640/* {{{ zend extension definition structure */
[1040]641static zend_extension xc_zend_extension_entry = {
[1026]642    XCACHE_NAME,
643    XCACHE_VERSION,
644    XCACHE_AUTHOR,
645    XCACHE_URL,
646    XCACHE_COPYRIGHT,
647    xc_zend_startup,
648    xc_zend_shutdown,
649    NULL,           /* activate_func_t */
650    NULL,           /* deactivate_func_t */
651    NULL,           /* message_handler_func_t */
652    NULL,           /* op_array_handler_func_t */
653    NULL,           /* statement_handler_func_t */
654    NULL,           /* fcall_begin_handler_func_t */
655    NULL,           /* fcall_end_handler_func_t */
656    NULL,           /* op_array_ctor_func_t */
657    NULL,           /* op_array_dtor_func_t */
658    STANDARD_ZEND_EXTENSION_PROPERTIES
659};
660/* }}} */
[82]661
[1026]662/* {{{ PHP_INI */
[1]663PHP_INI_BEGIN()
[1026]664    PHP_INI_ENTRY1     ("xcache.coredump_directory",      "", PHP_INI_SYSTEM, xcache_OnUpdateString,   &xc_coredump_dir)
[1067]665    PHP_INI_ENTRY1_EX  ("xcache.disable_on_crash",       "0", PHP_INI_SYSTEM, xcache_OnUpdateBool,     &xc_disable_on_crash, zend_ini_boolean_displayer_cb)
666    PHP_INI_ENTRY1_EX  ("xcache.test",                   "0", PHP_INI_SYSTEM, xcache_OnUpdateBool,     &xc_test,             zend_ini_boolean_displayer_cb)
[399]667    STD_PHP_INI_BOOLEAN("xcache.experimental",           "0", PHP_INI_ALL,    OnUpdateBool,        experimental,      zend_xcache_globals, xcache_globals)
[1]668PHP_INI_END()
669/* }}} */
[1026]670static PHP_MINFO_FUNCTION(xcache) /* {{{ */
[1]671{
672    php_info_print_table_start();
[1026]673    php_info_print_table_row(2, "XCache Version", XCACHE_VERSION);
[923]674#ifdef XCACHE_VERSION_REVISION
675    php_info_print_table_row(2, "Revision", "r" XCACHE_VERSION_REVISION);
676#endif
[26]677    php_info_print_table_row(2, "Modules Built", XCACHE_MODULES);
[1]678    php_info_print_table_end();
[82]679
[1]680    DISPLAY_INI_ENTRIES();
681}
682/* }}} */
[1026]683static PHP_MINIT_FUNCTION(xcache) /* {{{ */
[1]684{
[92]685#ifndef PHP_GINIT
[17]686    ZEND_INIT_MODULE_GLOBALS(xcache, xc_init_globals, xc_shutdown_globals);
[92]687#endif
[17]688    REGISTER_INI_ENTRIES();
689
[65]690    if (xc_coredump_dir && xc_coredump_dir[0]) {
[914]691        xcache_init_crash_handler();
[65]692    }
[1]693
[1129]694    if (strcmp(sapi_module.name, "cli") == 0) {
[1131]695        char *env;
[1129]696        if ((env = getenv("XCACHE_TEST")) != NULL) {
697            xc_test = atoi(env);
698        }
699    }
700
[1]701    xc_init_constant(module_number TSRMLS_CC);
[148]702    xc_shm_init_modules();
[1]703
[1047]704    /* must be the first */
705    xcache_zend_extension_add(&xc_zend_extension_entry, 1);
706#ifdef HAVE_XCACHE_OPTIMIZER
707    xc_optimizer_startup_module();
708#endif
709#ifdef HAVE_XCACHE_CACHER
710    xc_cacher_startup_module();
711#endif
[27]712#ifdef HAVE_XCACHE_COVERAGER
[1026]713    xc_coverager_startup_module();
[1]714#endif
[1026]715#ifdef HAVE_XCACHE_DISASSEMBLER
716    xc_disassembler_startup_module();
717#endif
[1045]718
[1]719    return SUCCESS;
720}
721/* }}} */
[1040]722static PHP_MSHUTDOWN_FUNCTION(xcache) /* {{{ */
[1]723{
[1040]724    if (old_compile_file && zend_compile_file == xc_check_initial_compile_file) {
725        zend_compile_file = old_compile_file;
726        old_compile_file = NULL;
[1]727    }
728
[65]729    if (xc_coredump_dir && xc_coredump_dir[0]) {
[914]730        xcache_restore_crash_handler();
[65]731    }
[1]732    if (xc_coredump_dir) {
733        pefree(xc_coredump_dir, 1);
734        xc_coredump_dir = NULL;
735    }
[92]736#ifndef PHP_GINIT
737#   ifdef ZTS
[25]738    ts_free_id(xcache_globals_id);
[92]739#   else
[1]740    xc_shutdown_globals(&xcache_globals TSRMLS_CC);
[92]741#   endif
[1]742#endif
743
744    UNREGISTER_INI_ENTRIES();
[1045]745    xcache_zend_extension_remove(&xc_zend_extension_entry);
[1]746    return SUCCESS;
747}
748/* }}} */
[492]749/* {{{ module dependencies */
[1026]750#ifdef STANDARD_MODULE_HEADER_EX
[847]751static zend_module_dep xcache_module_deps[] = {
[492]752    ZEND_MOD_REQUIRED("standard")
753    ZEND_MOD_CONFLICTS("apc")
754    ZEND_MOD_CONFLICTS("eAccelerator")
755    ZEND_MOD_CONFLICTS("Turck MMCache")
[983]756    ZEND_MOD_END
[492]757};
758#endif
759/* }}} */ 
[1]760/* {{{ module definition structure */
761zend_module_entry xcache_module_entry = {
[1026]762#ifdef STANDARD_MODULE_HEADER_EX
[492]763    STANDARD_MODULE_HEADER_EX,
764    NULL,
765    xcache_module_deps,
766#else
[1]767    STANDARD_MODULE_HEADER,
[492]768#endif
769    XCACHE_NAME,
[1]770    xcache_functions,
771    PHP_MINIT(xcache),
772    PHP_MSHUTDOWN(xcache),
[1040]773    NULL, /* RINIT */
774    NULL, /* RSHUTDOWN */
[1]775    PHP_MINFO(xcache),
776    XCACHE_VERSION,
[92]777#ifdef PHP_GINIT
778    PHP_MODULE_GLOBALS(xcache),
779    PHP_GINIT(xcache),
780    PHP_GSHUTDOWN(xcache),
781#endif
[1]782#ifdef ZEND_ENGINE_2
[1040]783    NULL /* ZEND_MODULE_POST_ZEND_DEACTIVATE_N */,
[1]784#else
785    NULL,
786    NULL,
787#endif
788    STANDARD_MODULE_PROPERTIES_EX
789};
790
791#ifdef COMPILE_DL_XCACHE
792ZEND_GET_MODULE(xcache)
793#endif
794/* }}} */
Note: See TracBrowser for help on using the repository browser.