source: trunk/xcache.c @ 1045

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

refactor: bring back compatibility with Zend Optimizer

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