source: trunk/xcache.c @ 1040

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

split cacher as sub module

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