source: trunk/xcache.c @ 1067

Last change on this file since 1067 was 1067, checked in by moo, 21 months ago

adds zend_ini_boolean_displayer_cb

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